Простой c malloc

это не работает:

void function(char* var)
{
    var = (char*) malloc (100);
}

int main()
{
    char* str;
    function(str);
    strcpy(str, "some random string");
    printf("%s\n", str);

    return 0;
}

это делает:

void function(char* var)
{
    //var = (char*) malloc (100);
}

int main()
{
    char* str;
    //function(str);
    str = (char*) malloc (100);
    strcpy(str, "some random string");
    printf("%s\n", str);

    return 0;
}

Почему?


person nunos    schedule 20.05.2010    source источник
comment
Когда вы говорите, что это не работает, было бы полезно знать, что в этом не работает. Детали хорошие.   -  person Matt Ball    schedule 20.05.2010
comment
Извини. Забыл упомянуть. Он компилируется, но когда я запускаю его, я получаю ошибку сегментации.   -  person nunos    schedule 20.05.2010
comment
Ваш код работает именно так, как должен. Если вы думаете, что что-то не работает, вы должны объяснить, что именно. Без этого ваш вопрос не имеет никакого смысла.   -  person AnT    schedule 20.05.2010
comment
Поскольку он компилируется, я предполагаю, что опечатка функции и функции в коде, вставленном выше, просто ради вопроса. Хотя, наверное, стоит пойти и исправить.   -  person Awaken    schedule 20.05.2010


Ответы (5)


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

void function(char** var)
{
    *var = malloc (100);
}

int main()
{
    char* str;
    function(&str);
    strcpy(str, "some random string");
    printf("%s\n", str);

    return 0;
}
person AraK    schedule 20.05.2010

Для этого вам нужно использовать указатель на указатель в качестве параметра, char **.
Когда вы передаете указатель в качестве параметра, он копируется, поэтому внутри функции вы получаете просто еще один указатель, указывающий на то же место.

Вам нужно получить char ** и сделать:

my_alloc_fun(void **ptr){
    *ptr= malloc(size);
}
void *myptr;
my_alloc_fun(&myptr);

Таким образом, вы получаете адрес указателя внутри функции, так что вы можете сделать так, чтобы исходный указатель указывал на вновь выделенную память.

person Arkaitz Jimenez    schedule 20.05.2010

Когда вы вызываете function(str), вы передаете значение str в function. Это значение представляет собой какое-то неинициализированное мусорное значение, потому что вы ничего не установили в main, но проблема не в этом.

Проблема в том, что function имеет свой собственный указатель, var, в который он помещает это мусорное значение, чтобы можно было сказать var points to the same thing (garbage) that str points to. Однако это не одна и та же переменная. Это две разные переменные, и изменение var не влияет на str.

Когда вы говорите var = (char*) malloc (100);, вы где-то выделяете память, а затем указываете var на нее. Теперь var указывает на другое место, чем str. Вы немедленно возвращаетесь из этой функции, теряя var и расположение этой памяти. Это, кстати, утечка памяти.

Когда вы вернетесь обратно к main, str останется таким же, как и всегда — указывает на мусор.

Числовой пример:

char *str;     // str -> 0xfeedface   (garbage)
function(str);

// inside 'function', an initialization like this occurs
char *var = str;  // var -> 0xfeedface (same garbage)
var = (char*) malloc (100); // var -> 0x12341234 (alloc'd memory)
return;

// back in 'main'
strcpy(str, "some random string"); // str still points to 0xfeedface!

Чтобы сделать это правильно, вам нужно изменить значение strs. Это означает, что function нужен указатель на str или указатель на указатель.

void function(char **var)
{
   *var = (char*)malloc(sizeof(char) * 100);
}

int main()
{
   char *str;
   function(&str);
   strncpy(str, "some random string", 99);
   ...
   free(str);  // important in general
}
person Phil    schedule 20.05.2010

Указатели такие же, как и любые другие переменные; разница только в том, что представляет их значение. В то время как double имеет значение, представляющее число с плавающей запятой двойной точности, а int имеет значение, представляющее целое число со знаком, указатель имеет значение, представляющее расположение другой переменной.

Сами указатели по-прежнему передаются по значению другим функциям; поэтому ваш пример не работает по той же причине, по которой не работает эта аналогичная функция:

void function(int var)
{
    var = 100;
}

int main()
{
    int num;
    function(num);
    printf("%d\n", num);

    return 0;
}

Ответ в обоих случаях один и тот же: Когда function() изменяет значение параметра var, изменяется только его локальная копия, а не переменная внутри main().

person caf    schedule 21.05.2010

См. мой ответ на Программирование на C: malloc() внутри другой функции за объяснение о том, как думать об этом.

person jamesdlin    schedule 20.05.2010