Память, выделенная malloc, не сохраняется за пределами области действия?
Привет,
Я немного новичок в функции malloc C, но из того, что я знаю, она должна хранить значение в куче, так что вы можете ссылаться на него с указателем из-за пределов исходной области видимости. Я создал тестовую программу, которая должна делать это, но я продолжаю получать значение 0 после запуска программы. Что я делаю неправильно?
#include <stdio.h>
#include <stdlib.h>
int f1(int *b) {
b = malloc(sizeof(int));
*b = 5;
}
int main(void) {
int *a;
f1(a);
printf("%d\n", a);
return 0;
}
Ответы
Ответ 1
Да! 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;
}
Ответ 2
Похоже, вы неправильно понимаете фундаментальную часть работы C, а именно, что это язык "pass-by-value". Чтобы 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()
был изменен, чтобы распечатать указанное значение, а не сам указатель.
Ответ 3
Сама память сохраняется, но она протекает, потому что вы не предоставляете выделенный указатель вызывающему. Кроме того, вы печатаете a
, когда вы должны печатать *a
. Наконец, вы не возвращаете int из f1
.
Try:
void f1(int **b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int *a;
f1(&a);
printf("%d\n", *a);
free(a);
return 0;
}
Ответ 4
Предположим, вы назначили значение NULL
для a перед вызовом функции f1
. Теперь путь f1 определен, он принимает свой аргумент (указатель на int
) по значению. То есть b
будет другой переменной типа int *
, которая будет копировать из a
. Так что b
тоже будет иметь значение NULL
. Теперь в f1
вы измените значение на b
, назначив ему адрес памяти, распределенный динамически, используя malloc
. Допустим, что адрес памяти 0x123
. В результате этого задания, b
изменил свое значение из NULL
до 0x123
но a
(в main
) продолжает удерживать NULL
, потому что изменение б не изменится a
, так как они представляют собой две отдельные переменные. В результате этого при возврате из функции f1
a останется неизменным.
Есть два способа решить эту проблему. Вы можете сделать функцию f1
вернуть значение измененного b
, а затем назначить его обратно в main
и два, вы можете передать адрес a, чтобы любые изменения, сделанные в f1
, повлияли a в 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;
}
Ответ 5
Ваша проблема на самом деле не связана с malloc, а скорее тем фактом, что вы передаете значение, которое в настоящее время содержит указатель, а не его адрес. Попробуйте следующее:
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int * a;
f1(&a);
printf("%d\n", *a);
return 0;
}
Передавая значение указателя так, как вы были, не удалось создать значение malloc, которое будет сохранено в указателе.
Ответ 6
Адрес int *b
удаляется при возврате функции. Чтобы сохранить его, вам нужно использовать указатель указателя
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}