Предупреждение Valgrind: я должен принять это серьезно - PullRequest
6 голосов
/ 28 января 2011

Справочная информация: У меня есть небольшая подпрограмма, которая имитирует fgets(character, 2, fp), за исключением того, что она берет символ из строки вместо потока. newBuff - это динамически размещаемая строка, передаваемая как параметр, и символ объявляется как char character[2].

Рутинное:

character[0] = newBuff[0];

character[1] = '\0';

strcpy(newBuff, newBuff+1);

strcpy копирует потерю информации, когда каждый символ читается из нее.

Проблема: Valgrind предупреждает меня о эта деятельность "Источник и место назначения перекрытие в strcpy (0x419b818, 0x419b819)».

Стоит ли беспокоиться об этом предупреждении?

Ответы [ 6 ]

11 голосов
/ 28 января 2011

Вероятно, стандарт не определяет, что происходит, когда эти буферы перекрываются.Так что да, valgrind правильно жаловаться на это.

На практике вы, скорее всего, обнаружите, что ваши strcpy копируются в порядке слева направо (например,while (*dst++ = *src++);) и это не проблема.Но это все еще неверно и может иметь проблемы при работе с другими библиотеками C.

Один из правильных стандартов написания этого будет:

memmove(newBuff, newBuff+1, strlen(newBuff));

, поскольку memmove определен для обработкиперекрытия.(Несмотря на то, что здесь вы в конечном итоге пройдете строку дважды, один раз, чтобы проверить длину, и один раз, чтобы скопировать. Я также выбрал ярлык, поскольку strlen(newBuff) должно равняться strlen(newBuff+1)+1, что я и написал изначально.)

5 голосов
/ 28 января 2011

Да, и вам также следует беспокоиться о том, что ваша функция имеет патологически плохую производительность (O(n^2) для задачи, которая должна быть O(n)). Перемещение всего содержимого строки назад символом каждый раз, когда вы читаете символ, - огромная трата времени. Вместо этого вы должны просто сохранить указатель на текущую позицию и увеличить его.

Ситуации, в которых вы нуждаетесь в memmove или его эквиваленте (копирование между перекрывающимися буферами) почти всегда указывает на недостаток дизайна. Часто это не просто недостаток в реализации, а в интерфейсе .

4 голосов
/ 28 января 2011

Да, вы должны беспокоиться.Стандарт C гласит, что поведение strcpy равно undefined , когда исходный и целевой объекты перекрываются.Неопределенное поведение означает, что оно может иногда работать, или оно может давать сбой, или оно может казаться успешным, но проявлять ошибку в другом месте программы.

4 голосов
/ 28 января 2011

Да - поведение strcpy определяется только в том случае, если source и dest не перекрываются.Вместо этого вы можете рассмотреть комбинацию strlen и memmove.

3 голосов
/ 28 января 2011

Поведение strcpy() официально не определено, если источник и назначение перекрываются.

На странице man для memcpy выдается предложение:

Функция memcpy () копирует n байтовиз области памяти s2 в область памяти s1.Если s1 и s2 перекрываются, поведение не определено.Приложения, в которых s1 и s2 могут перекрываться, должны использовать memmove (3).

2 голосов
/ 09 декабря 2012

Ответ - да: с некоторыми реализациями компилятора / библиотеки, самые новые, я полагаю, вы получите ложный результат. См. Как реализован strcpy? для примера.

...