Память, выделенная 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 но amain) продолжает удерживать 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;
}