2

I faced a question in an interview of a company, and I cannot figure out the reason about the answer.

void newArray(int* local, int size) 
{
     local = (int*) malloc( size * sizeof(int) );
}
int main() {
     int* ptr;
     newArray(ptr, 10);
}

Ans: This would cause memory leak and the program is not correct.

Does anyone know why this code cannot work?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 3
    Even if C wasn't passing the data by value, there's no call to `free` in this code, so it's gonna leak memory anyway. – ForceBru Mar 22 '17 at 16:16
  • @user2933783 I hope you passed the interview successfully. Otherwise it is entirely unclear why they spent their own time inviting you to interview and why they asked such questions.:) – Vlad from Moscow Mar 22 '17 at 16:21
  • I think your problem is with `pass by value` and `pass by pointer`. – Seek Addo Mar 22 '17 at 16:22
  • @user2933783 By the way their qualification as C programmers is not very high. At least they even do not know how main without parameters shall be declared.:) Also the second parameter should have type size_t instead of the type int.:) – Vlad from Moscow Mar 22 '17 at 16:23
  • You can use valgrind to check for any memory leaks in your C program. Please search for appropriate links and documentation on how to use valgrind to detect memory leak. – Gaurav Pathak Mar 22 '17 at 16:29
  • May I inquire which company what that? – 2501 Mar 22 '17 at 18:41

5 Answers5

8

In C, all function parameters are pass by value. So when the local variable local is modified inside of newArray, the change is not visible outside of the function. So the memory pointer is lost and you have a memory leak.

To fix the leak, the function should accept the address of a pointer (i.e. a pointer-to-pointer), then dereference that pointer so that ptr in main is updated. You would then need to call free to free the memory.

void newArray(int **local, int size) 
{
     *local = malloc( size * sizeof(int) );
}
int main() {
     int* ptr;
     newArray(&ptr, 10);
     free(ptr);
}

Also, don't cast the return value of malloc.

Community
  • 1
  • 1
dbush
  • 205,898
  • 23
  • 218
  • 273
  • in IDEs like visual studio, we will face an error if we don't cast the return value of malloc. – Fatemeh Karimi Mar 22 '17 at 19:53
  • 2
    @FatemehKarimi If you're compiling as C++, then yes you'll get an error. But if your source files are .c files, then you should be compiling as C where you should not make such a cast. – dbush Mar 22 '17 at 19:56
3

It cannot work since it changes the value of an argument inside a function, but since C is call by value that has no relation to the value of the variable that was used as that argument outside the function.

In other words, &local inside newArray() is not the same as &ptr in main(); they're different variables so changing one has no effect on the other.

unwind
  • 391,730
  • 64
  • 469
  • 606
3

You lose the reference to the malloced memory. This should be Ok.

void newArray(int** local, int size) 
{
     *local = (int*) malloc( size * sizeof(int) );
}
int main(c,v) char **v; {
    int* ptr;
    newArray(&ptr, 10);
    /* Do something with ptr? */
    free(ptr);
}
cleblanc
  • 3,678
  • 1
  • 13
  • 16
  • That still leaks memory — it's just from `main()` now rather than `newArray`. – Jonathan Leffler Mar 22 '17 at 17:01
  • hahaha, good point. I assume his actual program does something with the newArray(...) and free's it when finished, but you're right for this silly example I should add a `free(ptr)` before exiting main(...) – cleblanc Mar 22 '17 at 17:14
3

For starters this program

void newArray(int* local, int size) 
{
     local = (int*) malloc( size * sizeof(int) );
}
int main() {
     int* ptr;
     newArray(ptr, 10);
}

demonstrates that who asked the question in the interview is not strong himself as a C programmer.

First of all, according to the C Standard, function main without parameters shall be declared like

int main( void )

Secondly there is not any reason to declare the second parameter of the function newArray as having the type int instead of the type size_t because the standard function malloc used in the function has a single parameter of the type size_t.

Otherwise the function should check that the argument passed to the function is not a negative value.

As for the question then function parameters are its local variables. They are initialized by the supplied arguments. You can imagine the function definition and its call the following way

newArray(ptr, 10);

// ...

void newArray( /* int* local, int size */ ) 
{
    int *local = ptr;
    int size = 10;

    local = (int*) malloc( size * sizeof(int) );
}

As you can see it is the parameter (that is a local variable) local that is changed inside the function. The argument itself stays unchanged. Only the value of the argument is used to initialize initially the parameter. After exiting the function its local variables (including its parameters) are not alive and destroyed.

So the function indeed has a memory leak.

You should pass the argument by reference if you want that its value was changed in the function. For example

void newArray( int **local, size_t size  ) 
               ^^^^^^^^^^^^^^^^^^^^^^^^
{
    *local = (int*) malloc( size * sizeof(int) );
}

And the function should be called like

newArray( &ptr, 10 );

However a question arises what to do with the value of the pointer *local before reassigning it. Whether there should be called the function free before the call of malloc or not.

So a more clear function definition can look like

int * newArray( size_t size ) 
{
    return malloc( size * sizeof( int ) );
}

In this case it is the client of the function who decides what he should do with his own pointer which he is going to reassign.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

The pointer ptr is passed by value (like everything else in C). So, assigning the return value of malloc to local changes only local variable, not ptr in main().

As a result, there's no way to access the pointer returned by malloc() once the function newArray returns. Hence, it results in a memory leak.

It's similiar to:

void func(int x)
{
    x = 42;
}

int main(void)
{
   int y = 0;
   func(y);
   /* 'y' remains 0 */
}
P.P
  • 117,907
  • 20
  • 175
  • 238