Reputation:
I think I've got it down to the most basic case:
int main(int argc, char ** argv) {
int * arr;
foo(arr);
printf("car[3]=%d\n",arr[3]);
free (arr);
return 1;
}
void foo(int * arr) {
arr = (int*) malloc( sizeof(int)*25 );
arr[3] = 69;
}
The output is this:
> ./a.out
car[3]=-1869558540
a.out(4100) malloc: *** error for object 0x8fe01037: Non-aligned pointer
being freed
*** set a breakpoint in malloc_error_break to debug
>
If anyone can shed light on where my understanding is failing, it'd be greatly appreciated.
Upvotes: 16
Views: 19725
Reputation: 9370
Since your are passing the pointer by value, the arr pointer inside main isn't pointing to the allocated memory. This means two thing: you've got yourself a memory leak (NO, the memory isn't freed after the function foo completes), and when you access the arr pointer inside main you are accessing some arbitrary range of memory, hence you don't get 3 printed out and hence free() refuses to work. You're lucky you didn't get a segmentation fault when accessing arr[3] inside main.
Upvotes: 1
Reputation: 86423
You pass the pointer by value, not by reference, so whatever you do with arr inside foo will not make a difference outside the foo-function. As m_pGladiator wrote one way is to declare a reference to pointer like this (only possible in C++ btw. C does not know about references):
int main(int argc, char ** argv) {
int * arr;
foo(arr);
printf("car[3]=%d\n",arr[3]);
free (arr);
return 1;
}
void foo(int * &arr ) {
arr = (int*) malloc( sizeof(int)*25 );
arr[3] = 69;
}
Another (better imho) way is to not pass the pointer as an argument but to return a pointer:
int main(int argc, char ** argv) {
int * arr;
arr = foo();
printf("car[3]=%d\n",arr[3]);
free (arr);
return 1;
}
int * foo(void ) {
int * arr;
arr = (int*) malloc( sizeof(int)*25 );
arr[3] = 69;
return arr;
}
And you can pass a pointer to a pointer. That's the C way to pass by reference. Complicates the syntax a bit but well - that's how C is...
int main(int argc, char ** argv) {
int * arr;
foo(&arr);
printf("car[3]=%d\n",arr[3]);
free (arr);
return 1;
}
void foo(int ** arr ) {
(*arr) = (int*) malloc( sizeof(int)*25 );
(*arr)[3] = 69;
}
Upvotes: 47
Reputation: 13190
foo receives a local copy of the int pointer, alloactes memory to it and leaks that memory when it goes out of scope.
One way to fix this to get foo to return the pointer:
int * foo() {
return (int*) malloc( sizeof(int)*25 );
}
int main() {
int* arr = foo();
}
Another is to pass foo a pointer to a pointer
void foo(int ** arr) {
*arr = malloc(...);
}
int main() {
foo(&arr);
}
In C++ it is simpler to modify foo to accept a reference to a pointer. The only change you need in C++ is to change foo to
void foo(int * & arr)
Upvotes: 3
Reputation: 62789
You cannot change the value of your argument (arr) if it's not passed in by reference (&). In general, you would want to return the pointer, so your method should be:
arr=foo();
It's bad juju to try to reassign arguments; I don't recommend the (&) solution.
Upvotes: 0
Reputation: 14512
You've allocated arr in foo, but that pointers value is stored in the call stack. If you want to do this, do it like this:
void foo( int ** arr) {
*arr = (int *)malloc( sizeof(int) * 25 );
(*arr)[3] = 69;
}
And in main, simply pass a pointer to foo (like foo(&arr))
Upvotes: 6