Malloc внутри вызова функции, похоже, освобождается при возврате?
Вопрос
Я думаю, что разобрался с самым простым случаем:
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;
}
Результат таков:
> ./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
>
Если кто-нибудь сможет пролить свет на то, где не хватает моего понимания, я был бы очень признателен.
Решение
Вы передаете указатель по значению, а не по ссылке, поэтому все, что вы делаете с arr внутри foo, не будет иметь значения вне foo-функции.Как писал m_pGladiator, один из способов - объявить ссылку на указатель подобным образом (кстати, это возможно только в C ++.C не знает о ссылках):
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;
}
Другой (лучший имхо) способ - не передавать указатель в качестве аргумента, а возвращать указатель:
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;
}
И вы можете передать указатель на указатель.Это C-способ передачи по ссылке.Немного усложняет синтаксис, но хорошо - таков C...
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;
}
Другие советы
Вы выделили arr в foo, но значение этого указателя хранится в стеке вызовов.Если вы хотите это сделать, сделайте это вот так:
void foo( int ** arr) {
*arr = (int *)malloc( sizeof(int) * 25 );
(*arr)[3] = 69;
}
И в main просто передайте указатель на foo (например, foo(&arr))
foo получает локальную копию указателя int, выделяет ей всю память и пропускает эту память, когда она выходит за пределы области видимости.
Один из способов исправить это - заставить foo возвращать указатель:
int * foo() {
return (int*) malloc( sizeof(int)*25 );
}
int main() {
int* arr = foo();
}
Другой способ - передать foo указатель на указатель
void foo(int ** arr) {
*arr = malloc(...);
}
int main() {
foo(&arr);
}
В C ++ проще изменить foo, чтобы он принимал ссылку на указатель.Единственное изменение, которое вам нужно в C ++, - это изменить foo на
void foo(int * & arr)
Поскольку вы передаете указатель по значению, указатель arr внутри main не указывает на выделенную память.Это означает две вещи:у вас произошла утечка памяти (НЕТ, память не освобождается после завершения функции foo), и когда вы обращаетесь к указателю arr внутри main, вы получаете доступ к некоторому произвольному диапазону памяти, следовательно, вы не распечатываете 3 и, следовательно, free() отказывается работать.Вам повезло, что вы не получили ошибку сегментации при доступе к arr [3] внутри main.
Вы не можете изменить значение вашего аргумента (arr), если оно не передано по ссылке (&).В общем, вы хотели бы вернуть указатель, поэтому ваш метод должен быть:
arr=foo();
Пытаться переназначать аргументы - плохая шутка;Я не рекомендую использовать (&) решение.