Кто-то еще извинился за опоздание на вечеринку - два с половиной месяца назад. О, хорошо, я провожу довольно много времени, занимаясь археологией программного обеспечения.
Меня интересует, что никто не прокомментировал явно утечку памяти в оригинальном дизайне или ошибку «один за другим». И именно наблюдение за утечкой памяти говорит мне точно, почему вы получаете ошибку двойного освобождения (потому что, если быть точным, вы освобождаете одну и ту же память несколько раз - и вы делаете это после того, как попираете уже освобожденную память).
Перед проведением анализа я согласен с теми, кто говорит, что ваш интерфейс менее звездный; однако, если вы столкнулись с проблемами утечки / утечки памяти и задокументировали требование «должна быть выделена память», это может быть «ОК».
В чем проблемы? Ну, вы передаете буфер функции realloc (), и realloc () возвращает вам новый указатель на область, которую вы должны использовать - и вы игнорируете это возвращаемое значение. Следовательно, realloc (), вероятно, освободил исходную память, а затем вы снова передаете ему тот же указатель, и он жалуется, что вы освобождаете одну и ту же память дважды, потому что вы снова передаете ей исходное значение. Это не только приводит к утечке памяти, но и означает, что вы продолжаете использовать исходное пространство - и выстрел Джона Дауни в темноте указывает на то, что вы неправильно используете realloc (), но не подчеркивает, насколько серьезно вы это делаете. Также есть ошибка «один за другим», потому что вы не выделяете достаточно места для NUL '\ 0', заканчивающего строку.
Утечка памяти происходит из-за того, что вы не предоставляете механизм, чтобы сообщить вызывающей стороне о последнем значении строки. Поскольку вы продолжали топтать исходную строку плюс пробел после нее, похоже, что код работал, но если ваш вызывающий код освободил пробел, он также получит ошибку без двойного освобождения, или он может получить дамп ядра или эквивалент, потому что информация управления памятью полностью зашифрована.
Ваш код также не защищает от неопределенного роста - рассмотрите возможность замены 'Noel' на 'Joyeux Noel'. Каждый раз вы добавляете 7 символов, но вы найдете другой Ноэль в замененном тексте, расширяете его и так далее, и так далее. Мое исправление (ниже) не решает эту проблему - простое решение, вероятно, состоит в том, чтобы проверить, появляется ли строка поиска в строке замены; альтернатива - пропустить строку замены и продолжить поиск после нее. Второй имеет несколько нетривиальных проблем с кодированием.
Итак, моя рекомендуемая версия вызываемой функции:
char *strrep(char *input, char *search, char *replace) {
int searchLen = strlen(search);
int replaceLen = strlen(replace);
int delta = replaceLen - searchLen;
char *find = input;
while ((find = strstr(find, search)) != 0) {
if (delta > 0) {
input = realloc(input, strlen(input) + delta + 1);
find = strstr(input, search);
}
memmove(find + replaceLen, find + searchLen, strlen(input) + 1 - (find - input));
memmove(find, replace, replaceLen);
}
return(input);
}
Этот код не обнаруживает ошибки выделения памяти - и, вероятно, аварийно завершает работу (но если нет, то приводит к утечке памяти) в случае сбоя функции realloc (). См. Книгу Стива Магуайра «Написание твердого кода» для подробного обсуждения вопросов управления памятью.