Память, выделенная с помощью malloc, не сохраняется вне области действия функции?
Привет,
Я немного новичок в функции malloc C, но из того, что я знаю, она должна хранить значение в куче, так что вы можете ссылаться на него с указателем из-за пределов исходной области видимости. Я создал тестовую программу, которая должна делать это, но я продолжаю получать значение 0 после запуска программы. Что я делаю неправильно?
int f1(int * b) {
b = malloc(sizeof(int));
*b = 5;
}
int main() {
int * a;
f1(a);
printf("%d\n", a);
return 0;
}
6 ответов
Да! a
передается по значению, так что указатель b
в функции f1
будет местный.. либо возврат b
,
int *f1() {
int * b = malloc(sizeof(int));
*b = 5;
return b;
}
int main() {
int * a;
a = f1();
printf("%d\n", *a);
// keep it clean :
free(a);
return 0;
}
или пройти a
адрес
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int * a;
f1(&a);
printf("%d\n", *a);
// keep it clean :
free(a);
return 0;
}
Похоже, вы неправильно понимаете основную часть работы C, а именно то, что это язык "передачи по значению". Для того чтобы main()
Чтобы узнать о выделенной памяти, вы должны вернуть ее обратно. Следующий код сделает вам то, что вы хотите:
int f1(int **b)
{
*b = malloc(sizeof(int));
**b = 5;
}
int main(int argc, char **argv)
{
int *a;
f1(&a);
printf("%d\n", *a);
return 0;
}
Есть несколько различий между этим кодом и вашим; во-первых, подпись f1()
изменилось, так что он может вернуть результат malloc()
вызов в переданном указателе. Далее звонок f1()
был изменен, чтобы передать адрес a
скорее, чем a
сам по себе - важно, если вы хотите, чтобы он был "заполнен" f1()
, так сказать. Наконец, printf()
в main()
был изменен, чтобы печатать указанное значение, а не сам указатель.
Сама память сохраняется, но она протекает, потому что вы не предоставляете выделенный указатель вызывающей стороне. Кроме того, вы печатаете a
когда вы должны печатать *a
, Наконец, вы не возвращаете int из f1
,
Пытаться:
void f1(int **b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int *a;
f1(&a);
printf("%d\n", *a);
free(a);
return 0;
}
Предположим, вы назначаете значение NULL
перед вызовом функции f1
, Теперь способ определения f1 принимает аргумент (указатель на int
) по значению. То есть b
будет другая переменная типа int *
которая будет копией a
, Так b
тоже будет иметь значение NULL
, Сейчас в f1
вы меняете значение на b
присваивая ему адрес памяти, выделенный динамически, используя malloc
, Допустим, что адрес памяти 0x123
, В результате этого задания b
изменил свое значение с NULL
в 0x123
но a
(в main
) продолжает держать NULL
потому что изменение б не изменится a
, поскольку они являются двумя отдельными переменными. В результате этого, когда вы возвращаетесь из функции f1
А останется без изменений.
Есть 2 способа решить эту проблему. Один, вы можете сделать функцию f1
вернуть значение измененного b
а затем назначить его обратно в main
и во-вторых, вы можете передать по адресу, так что любые изменения, сделанные в f1
повлияет на в main
тоже.
// f1 now returns the value of b.
int* f1() {
int *b = malloc(sizeof(int));
*b = 5;
return b;
}
int main() {
int *a = NULL;
a = f1(); // assign the return value of f1 to a.
printf("%d\n", *a); // prints 5...not its *a not just a.
return 0;
}
,
// f1 now takes the address of a.
void f1(int **b) {
*b = malloc(sizeof(int)); // you are actually altering a indirectly.
**b = 5;
}
int main() {
int *a = NULL;
f1(&a); // now pass the address of a to f1.
printf("%d\n", *a); // prints 5...not its *a not just a.
return 0;
}
Ваша проблема на самом деле не связана с malloc, а скорее с тем, что вы передаете значение, которое содержит указатель, а не его адрес. Попробуйте следующее:
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int * a;
f1(&a);
printf("%d\n", *a);
return 0;
}
Передавая значение указателя, каким вы были, не было способа сохранить созданное значение malloc в указателе.
Адрес int *b
удаляется при возврате функции. Чтобы сохранить его, вам нужно использовать указатель указателя
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}