2013-04-08 3 views
0

После выполнения этой функции многие (не уверены точно сколько) раз, это seg ошибки в простом распределении памяти. Почему это внезапно произойдет? В GDB я заметил что-то странное. В функции, которая его вызывает, обычно имеется 6-значное длинное шестнадцатеричное значение для wrd (например, wrd = 0x605140), однако при вызове, где он сбой, шестнадцатеричное значение составляет всего две цифры. (WRD = 0x21). Я также проверил wrd-> длину, и это 3.Ошибка сегментации на malloc

линия, что она падает на это ...

char *word_temp = malloc(wrd->length * sizeof(char)); 

EDIT:

Вот код, который создает WRD ...

while(fgets(input, 100, src) != 0) 
{ 
    int i = 0; 
    while(input[i] != '\0') 
    { 
     i++; 
    } 

    struct word *wrd = malloc(sizeof(struct word)); 
    wrd->letters = input; 
    wrd->length = i; 

Если у меня переполнение, как я могу это исправить?

+5

Скорее всего, 'wrd' не указывает на что-то действительное. – chris

+4

Если у вас есть этот параметр, вы должны запустить приложение под Valgrind. Очень вероятно, что вы повредили кучу, переполнив динамически выделенный буфер где-нибудь. –

+1

Обычно такие проблемы связаны с ошибками указателя (переполнение буфера и т. Д.), Возможно, в другом месте программы. Здесь может случиться так, что вы не учитываете нулевой ограничитель строк? Трудно сказать с таким маленьким контекстом. – metal

ответ

0

Похож, что wrd->length не содержит завершающего '\0'.

Fix 1, выделить word_temp так:

char *word_temp = malloc(wrd->length + 1); 

Fix 2, включают в себя '\ 0' путем изменения вам длины счетчика циклов:

int i = 0; 
while(input[i++] != '\0') {} 

Это увеличит i один больше времени, чем код в вопросе, который легко увидеть, если вы считаете случай input пустым.

Обратите внимание, что вам нужно либо исправить 1, либо исправить 2, а не оба. Выберите, что когда-либо работает с остальной частью вашего кода.


Вы, вероятно, второй выпуск этой линии:

wrd->letters = input; 

Он не копирует ввод, он копирует указатель. Если вы измените содержимое input, содержимое wrd->letters тоже изменится, поскольку они указывают на то же место в памяти. Кроме того, если input является локальным массивом символов, то после того, как он выходит из области видимости, wrd->letters становится висячим указателем, который будет перезаписан другими данными, а после его модификации это приведет к повреждению памяти.

Возможные исправления (в зависимости от остальной части кода) является использование strdup:

wrd->letters = strdup(input); 

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

free(wrd->letters); 

О wrd является 0x21, что указывает на повреждение памяти или что у вас на самом деле есть две отдельные переменные wrd, а одна из них оставлена неинициализированный.

Например, возможно, wrd является параметром функции struct word *wrd, и в этом случае вы изменяете только локальное значение в функции, оно не возвращается обратно вызывающему.Чтобы изменить указатель вызывающего абонента, вам нужно указать указатель на указатель: struct word **wrd, а затем сделать (*wrd) = malloc... и (*wrd)->letters... и т. Д.

+0

Это не исправить. – SwiftCore

+1

'sizeof (char)' всегда гарантированно будет '1'. Нет необходимости писать так. Это не идиоматично. – Wiz

+0

@SwiftCore Добавил больше материала для ответа. Это довольно спекулятивно, и если это не поможет, оно все равно может дать вам некоторые идеи о том, как изменить ваш вопрос, чтобы быть более информативным. – hyde

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