Память, выделенная с помощью malloc, не сохраняется вне области действия функции? - PullRequest
12 голосов
/ 25 марта 2010

Привет

Я немного новичок в функции 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;
}

Ответы [ 6 ]

24 голосов
/ 25 марта 2010

Да! 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;
}
9 голосов
/ 25 марта 2010

Похоже, вы неправильно понимаете основную часть работы 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 - важно, если вы хотите, чтобы он был "заполнен", так сказать, на 1010 *. Наконец, printf() в main() был изменен, чтобы печатать указанное значение, а не сам указатель.

6 голосов
/ 25 марта 2010

Сама память сохраняется, но она протекает, потому что вы не предоставляете выделенный указатель вызывающей стороне. Кроме того, вы печатаете 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;
}
5 голосов
/ 25 марта 2010

Предположим, что вы присваиваете значение NULL до вызова функции f1. Теперь способ определения f1 принимает его аргумент (указатель на int) по значению. То есть b будет другой переменной типа int *, которая будет copy из a. Так что b тоже будет иметь значение NULL. Теперь в f1 вы меняете значение на b, присваивая ему адрес памяти, динамически выделяемый с помощью malloc. Допустим, адрес памяти равен 0x123. В результате этого присваивания значение b изменилось с NULL на 0x123, но amain) продолжает удерживать NULL, поскольку изменение b не изменит a, так как это две отдельные переменные. В результате этого при возврате из функции f1 a останется без изменений.

Есть 2 способа решить эту проблему. Во-первых, вы можете заставить функцию f1 возвращать значение измененного b, а затем присвоить его обратно в in main, а во-вторых, вы можете передать a по адресу, чтобы любые изменения, сделанные в 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;
}
0 голосов
/ 25 марта 2010

Адрес int *b удаляется при возврате функции. Чтобы сохранить его, необходимо использовать указатель указателя

int f1(int ** b) {
   *b = malloc(sizeof(int));
   **b = 5;
}
0 голосов
/ 25 марта 2010

Ваша проблема на самом деле связана не с malloc, а с тем фактом, что вы передаете значение, которое удерживает указатель, а не его адрес. Попробуйте следующее:

int f1(int ** b) {
    *b = malloc(sizeof(int)); 
    **b = 5;
}

int main() {
    int * a;
    f1(&a);
    printf("%d\n", *a);
    return 0;
}

Передав значение указателя, каким вы были, невозможно было создать значение malloc, сохраненное в указателе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...