2013-08-27 2 views
3

Допустим у нас есть:Использование strdup()

-структуру
struct Person { 
    char *name; 
}; 

struct Person *Person_create(char *name){ 
    struct Person *who = malloc(sizeof(struct Person)); 
    assert(who != NULL); 
    who->name = strdup(name); 
    return who; 
} 

void Person_destroy(struct Person *who){ 
    assert(who != NULL); 
    free(who->name); 
    free(who); 
} 

И главная функция:

int main(int argc,char *argv[]){ 

    struct Person *mike = Person_create("mike"); 
    Person_print(mike); 
    Person_destroy(mike); 

    return 0; 
} 

Приведенный выше код не будет работать должным образом без функции strdup(). Вальгринд говорит, что адрес, который вы пытаетесь освободить бесплатно (who-> name), не является malloc'd. Какая история за этим, разве я не помню эту память, когда я строил структуру? И какая разница делает strdup()?

+0

Вы уверены, что это соответствует вашему тестовому образцу? – ouah

+0

Да, исходный код был более сложным, но когда я запускаю эту программу, он говорит: *** Ошибка в './ex1 ': free(): недопустимый указатель: 0x00000000004006fd ***" –

+1

этот код выглядит нормально. Здесь есть два варианта. Либо 'Person_print' делает некоторые неприятные записи, которые, я сомневаюсь, или ваша программа отличается от этого теста. – ouah

ответ

5

В вашем коде каждый объект Person имеет два независимых блока памяти: объект struct Person и отдельный блок памяти для имени. Этот отдельный блок памяти указывается указателем name внутри структуры. Когда вы назначаете struct Person с помощью malloc, вы не выделяете никакой памяти для имени. Это, опять же, независимый блок памяти, который должен быть выделен независимо.

Как вы планируете распределять память для имени, полностью зависит от вас. Если вы используете strdup (который по существу является оберткой для malloc), как в вашем коде выше, тогда вам нужно будет освободить его на free в конце.

Вы не объяснили, что вы подразумеваете под «без функции strdup()». Как вы выглядели без кода? Если вы просто сделали

who->name = name; 

тогда вы сделали, что who->name указатель указывает непосредственно к буквальному памяти строки, занятой буквального "mike". Строковые литералы находятся в статической памяти. Вам не разрешено использовать free. Это то, что говорит вам Вальгринд.

+0

Да, действительно, это так, удаление строки бесплатно (who-> name) решает все ошибки, спасибо. –

-3

strdup do noes call malloc, это только операция с строкой. вы только malloc указатель на структуру, а не внутренний член

+2

Документация не согласна: «Память для новой строки получена с помощью malloc (3) и может быть освобождена со свободным (3)». –

0

Mallocing struct выделяет память для имени указателя, но не выделяет память для указания имени. В этот момент who-> name будет какой-то случайной мусорной ценностью, поэтому освобождение не имеет смысла.

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

Смежные вопросы