Aditya Kumar Praharaj
Aditya Kumar Praharaj

Reputation: 309

Scope of Heap Memory

As far as I know Heaps are supposed to be global in nature, aren't they? So we should be able to access the heap memory anywhere we want in our functions. Then why does the following code segfault (Segmentation Fault)?

#include <stdio.h>
using namespace std;

void A(int* x)
{
  x = new int[10];
  for(int i = 0; i< 10; i++)
  {
    x[i] = i;
  }
}

void B(int *x)
{
  printf("%d", x[8]);
}

int main()
{
  int* a = NULL;
  A(a);
  B(a);
  return 0;
}

Upvotes: 3

Views: 885

Answers (4)

R Sahu
R Sahu

Reputation: 206577

Question: As far as I know Heaps are supposed to be global in nature, aren't they?

Answer: Yes.

Statement: So we should be able to access the heap memory anywhere we want in our functions.

Respons: Yes, we will be able to, as long as we know the heap memory value.

Question: Then why does the following code segfault (Segmentation Fault)?

Answer: Allocating heap memory in one function does not guarantee that the memory value is visible from other functions. The address returned by operator new has to be somehow made available to other functions. You can do this in couple of ways:

  1. Change the argument type to int*& a, as suggested by Subhajit.

  2. Let A return the allocated memory address.

    int* A()
    {
      int* x = new int[10];
      for(int i = 0; i< 10; i++)
      {
        x[i] = i;
      }
      return x;
    }
    

Upvotes: 2

Brian Cain
Brian Cain

Reputation: 14619

As other answer(s) indicate, indeed the problem is that the memory allocated in A() is not passed to B().

But it's really excellent to note that you can detect this problem using static analysis, with freely available tools.

When I ran clang++ version 3.4 on your example, it gives:

$ make
clang++ -Wall -Wextra --analyze   -c -o go.o go.cpp
go.cpp:16:16: warning: Array access (from variable 'x') results in a null pointer dereference
  printf("%d", x[8]);
               ^~~~
1 warning generated.

How awesome is that‽ In this particular standalone example the additional time for the compiler to evaluate the paths was negligible. It may be a bit more overhead on "real" code (not synthetic examples like these). But it's almost certainly worth it for most users.

Upvotes: 2

Subhajit
Subhajit

Reputation: 320

Both A(a) and B(a) call are By Value for a. So, any change inside A() or B() will not affect from the caller.

Please call as,

void A(int*& a);

Upvotes: 1

hmjd
hmjd

Reputation: 121971

A segmentation fault occurs because the pointer a is being passed by value so the changes made within A() are not visible to the caller, resulting in a NULL pointer being dereferenced within B(). To correct, pass the pointer by reference to A():

void A(int*& x)

Upvotes: 9

Related Questions