2014-10-22 7 views
1

Я получаю ошибку, которую вы можете увидеть в названии, и я не могу понять, почему.glibc обнаружен - двойной свободный или коррупционный (! Prev)

Код:

#include <cstdlib> 
#include <cstdio> 

struct CData { 
    int* num; 
    char* adr; 
    char* ph; 

    void (*init)(CData* owner); 
    void (*del)(CData* owner); 
    char* (*getAdr)(CData* owner); 
    void (*setAdr)(CData* owner, char* adr); 
}; 

void CData_init(CData* owner) { 
    owner->num = (int*)malloc(sizeof(int)); 
    owner->adr = (char*)malloc(sizeof(char)*255); 
    owner->ph = (char*)malloc(sizeof(char)*255); 
} 

void CData_del(CData* owner) { 
    free(owner->num); 
    free(owner->adr); 
    free(owner->ph); 
} 

char* CData_getAdr(CData* owner) { 
    return owner->adr; 
} 

void CData_setAdr(CData* owner, char* adr) { 
    owner->adr = adr; 
} 

int main() { 
    CData* data = (CData*)malloc(sizeof(CData)); 

    data->init = CData_init; 
    data->del = CData_del; 
    data->getAdr = CData_getAdr; 
    data->setAdr = CData_setAdr; 

    data->init(data); 

    data->setAdr(data, "asdasd"); 
    printf("%d", data->getAdr(data)); 

    data->del(data); 

    free(data); 

    return 0; 
} 

Так что я думаю, что ошибка вызвана полукокс * манипуляциями, но я не знаю, почему.

Что я хочу сделать, так это то, что я могу передать строку как параметр в data->setAdr, и я хочу, чтобы она была назначена переменной после этого.

Составление линии:

gcc -o test main.cpp 
+0

«double free» - это должно что-то сказать, может быть, что-то вроде «double' free() '» – bitcell

+0

Вам не разрешено освобождать строковые литералы. (И вы утечка предыдущего значения в 'setAdr'.) – Mat

+0

Да, я сделал такое предположение сначала, но где? – ohyou

ответ

2

data->setAdr(data, "asdasd"); является проблематичным.

Вы устанавливаете адрес блока памяти, который не выделяется malloc, а затем пытается освободить его с помощью free. Освобождение таких блоков памяти (не выделенных malloc), кроме указателя NULL, приводит к неопределенному поведению.

Это также утечка как минимум 255 байт памяти в вашем случае. valgrind может помочь вам лучше понять в этом случае.

Изменение следующая функция должна это исправить (Переименовать его соответствующим образом)

void CData_setAdr(CData* owner, char* adr) { 
    strcpy(owner->adr, adr); /* include cstring */ 
} 
+0

Так что в моем случае мне нужно просто сохранить указатель на статическую строку и не заботиться о распределении памяти? – ohyou

+0

В этом случае вы не должны передавать права собственности на строку в «CData», а сеттер должен выделять и освобождать строки. Вы не можете смешивать распределение и бесплатные правила по всем модулям. Чтобы включить оба способа настройки, вам нужно немного больше фреймворка, чтобы определить, когда бесплатно и когда не освобождать. –

+0

Получил, спасибо. – ohyou

1

Проблема здесь:

data->setAdr(data, "asdasd"); 

Ваша реализация:

void CData_setAdr(CData* owner, char* adr) { 
    owner->adr = adr; 
} 

Таким образом, вы перезаписать адрес ранее зарегистрированной памяти malloc() с указателем на co nstant, поэтому, когда вы делаете data->del(data);, glibc предупреждает, что вы освобождаете память, которая не была выделена, а также потерянная ранее память. Попробуйте вместо этого:

void CData_setAdr(CData* owner, char* adr) { 
    strcpy(owner->adr, adr); 
} 

Не забудьте добавить подходящую проверку ошибок и т. Д.!

+0

Я вижу сейчас, спасибо. – ohyou

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