2016-07-04 1 views
1

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

Мой код таким образом, что в функции main(), я делаю вызов функции с определением char * reverseComplement(char * pattern); как таковой:

char * rev = reverseComplement(dna_input); 

где dna_input является char указатель на блок выделенной памяти, который был выделен в пределах main(). В функции reverseComplement() есть строка, в которой я выделяю память, а затем возвращаю указатель на этот блок памяти в самом конце.

... 
... 
char * revcomplpattern = (char *)malloc(strlen(pattern)); 
... 
... 
return revcomplpattern; 

Одна из причин, я думал, что может быть причиной проблемы является то, что после того, как функция reverseComplement() завершения выполнения, его стек получает снесено, так что я потерял бы доступ к памяти в куче. Но это не должно быть из-за того, что я прошел над рукояткой памяти, выделенной кучей, от revcomplpattern, которая находилась в reverseComplement() до rev, которая находится в main(). Поэтому free(rev) в main() должен выполнить эту работу.

Я не знаю, что я могу делать неправильно здесь, и любая помощь очень ценится!

+6

'malloc (strlen (pattern))' -> 'malloc (strlen (pattern) +1)' – BLUEPIXY

+0

Это не лучшая привычка выделять память в функции, и они заставляют ее отвечать на вызов 'free() '. – babon

+0

Прежде всего, удалите бросок, а затем посмотрите, что говорит вам компилятор. – alk

ответ

-1

Возможно, вы повредили память, прежде чем возвращать управление в main()? Освобождение «допустимого» блока памяти может быть неудачным, потому что ваша куча malloc уже повреждена. В качестве альтернативы, возможно, некоторые кодеки ошибок в reverseComplement() уже освобождают эту память?

+2

«Возможно, ... возможно ... *», может быть, этот ответ лучше подходит для комментариев. – alk

0

... где dna_input - это указатель на символ выделенной памяти, который был выделен в main(). В функции reverseComplement() есть строка, в которой я выделяю память, а затем возвращаю указатель на этот блок памяти в самом конце.

Ваша идея говорит мне, что вы выделяете память и каким-то образом используете эту память в функции reverseComplement(), но в функции вы выделяете еще один блок памяти. Я не знаю, почему.

... проблема, где я получаю двойную бесплатно или коррупционную ошибку ...

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

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

char *getnewblock(int size) 
{ 
    char *secondblock=malloc(size); 
    return secondblock; 
} 

int main() 
{ 
    char *myblock = malloc(1000); 
    char *myblock2 = getnewblock(5000); 
    free(myblock); 
    free(myblock2); 
    return 0; 
} 

выше программа выделяет 1000 байт памяти, то вызывает функцию выделить Затем 5000 байтов памяти освобождает оба блока памяти.

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

void insertfirstchar(char *block,char onechar) 
{ 
    block[0]=onechar; 
} 

int main() 
{ 
    char *myblock = malloc(1000); 
    insertfirstchar(myblock,'A'); 
    free(myblock); 
    return 0; 
} 

В приведенной выше программе, 1000 байт выделяется, то функция чтобы сделать первый байт блока памяти буквой «А», тогда память освобождается. Эта последняя программа может использоваться в качестве отправной точки.

+0

Да, это то, о чем я и думал, но это заставит мою функцию «reverseComplement()» принять дополнительный аргумент, который я бы предпочел не делать. Теперь мне любопытно, что в профессиональных проектах они следуют предложенной вами практике, или мой стиль может быть принят? – AKKA

0

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

Оказывается, что я сделал, когда я выделил

char * revcomplpattern = (char *)malloc(strlen(pattern)); 

был немедленным последующим этих линий

int strend = strlen(pattern)/sizeof(char) -1 ; 
revcomplpattern[strend+1] = '\0'; 

где моя цель состояла в том, чтобы гарантировать, что revcomplpattern будет сделано в строку, как я вставил нулевое завершение в конце. Оказывается, что при индексировании [strend+1] я фактически касался нераспределенной позиции в памяти! После коррекции malloc() вызова с дополнительным пространством для более одного символа

char * revcomplpattern = (char *)malloc(strlen(pattern) + 1 * sizeof(char)); 

Вызов к free(rev) не бросает ошибку! Теперь все отлично работает, и Valgrind не показывает ошибок! Специальный крик для @tofro и @jdigital для вашего совета. Когда я использовал valgrind, он начал рассказывать мне, что произошла ошибка в strlen и malloc, которые я не мог понять сначала, пока я не сузил ее до этой линии и не посмотрел на нее и не понял, что случилось.

Человек, я чувствую, что GCC дает очень загадочные сообщения об ошибках, которые не очень помогают. Я действительно озадачен сейчас, если кто-нибудь может ответить, почему моя ошибка не выбрала SEGFAULT? Я думал, что это вызовет segfault, так как я касался нераспределенной части памяти ???

Тем не менее, спасибо всем за вашу помощь!

+0

'sizeof (char)' равно '1' по определению. Если бы это не было: 'malloc (strlen (pattern) + 1 * sizeof (char));' будет терпеть неудачу, так как это должно быть 'malloc ((strlen (pattern) + 1) * sizeof (char));' – alk

+0

И все же, если это действительно * код * C, просто удалите все эти приведения в 'malloc()', поскольку он не нужен и не рекомендуется никоим образом. Это отличается от C++. – alk

+0

И наконец: Выписывание границ допустимой памяти в C-причине * Неопределенное поведение *. С этого момента на * ничего * может случиться, когда «* anything *» является исключением исключения для сегментации или просто ничего или ... или ... – alk

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