сценарии сбоя для memcpy - PullRequest
0 голосов
/ 22 января 2019

Я пытаюсь понять сценарии, в которых вызов memcpy может произойти сбой молча, потому что неверные указатели приведут к нарушению доступа / segfaults.Также будут проблемы в случае наложения указателей.Кроме них, есть ли другие способы, которыми вызов memcpy может потерпеть неудачу?Или мы можем считать, что все пройдет без ошибок.Как это проверить?

Ответы [ 3 ]

0 голосов
/ 23 января 2019

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

0 голосов
/ 23 января 2019

Я пытаюсь понять сценарии, в которых вызов memcpy может произойти сбой молча, потому что неверные указатели приведут к нарушению доступа / segfaults.

Обычно, когда есть нарушение доступа / segfault,программное обеспечение громко терпит неудачу.Это может произойти, если memcpy() даны хитрые указатели или неправильный размер, который включает «правильные указатели, но куча была повреждена» (например, метаданные, которые malloc() / free() использует для отслеживания выделенных областей, были перезаписаны ошибкойпобуждая free() вернуть основную виртуальную ОЗУ ядру для области, которая должна была быть сохранена, и вызывая сбой memcpy() с нарушением доступа, потому что область, к которой он должен был иметь доступ, не может бытьдоступ).

Другие случаи являются внешними условиями отказа.Если операционная система решила отправить некоторые данные в пространство подкачки, но при попытке получить данные обратно из пространства подкачки при попытке получить к ним доступ при попытке получить к ней доступ, ОС мало что может с этим поделать (ваш процесси любой другой процесс, использующий эти данные, не может продолжаться правильно).Если вы используете ECC RAM, а контроллер памяти сообщает о неисправимой ошибке с используемой RAM, она похожа.Для ОС также возможно использовать «ленивое выделение страниц» (например, страницы памяти выделяются, когда вы пишете им, а не когда вы думали, что вы их выделили) и «сверх фиксация» (притворяются, что выделено больше страниц, чем может быть предоставлено).), так что когда memcpy() пишет в область, которая была выделена, ОС не может обработать ее (например, она запускает «OOM / out of memory killer», который завершает процесс для освобождения некоторой оперативной памяти).Наконец, возможно, что код будет поврежден (например, неисправное ОЗУ без ECC, злонамеренная атака, такая как «Rowhammer», поврежденная общая библиотека, ...), так что (например) использование memcpy() вызывает SIGILL.Конечно, все эти вещи не связаны с самим memcpy() и могут так же легко происходить где-либо еще.

Также будут проблемы в случае перекрывающихся указателей.

Да.Некоторые (большинство) реализаций memcpy() оптимизированы для копирования больших блоков (например, оптимизированы для использования SSE на 80x86 и перемещения 16 байтов за раз), где, если области перекрываются, данные искажаются.Некоторые (большинство) реализаций memcpy() предполагают, что он может копировать данные в одном конкретном направлении, что приведет к повреждению данных, если области будут перекрываться неправильным образом (например, если реализация использует направление «сначала самый низкий адрес» и область назначения).перекрывается и имеет более высокий адрес, чем источник, затем запись в место назначения перезапишет данные источника, которые еще не были скопированы).

Кроме этих, есть ли другие способы вызова memcpyможет произойти сбой?

Нет, я думаю, что я рассмотрел все возможные случаи сбоя выше.

Или мы можем считать, что он пройдет все время без каких-либо ошибок.Как это проверить?

Для проблемы «перекрывающихся областей» не составит труда написать обертку вокруг memcpy(), которая обнаруживает перекрытие и генерирует ошибку (чтобы не было молчаповрежденные данные).К сожалению, это обнаруживает проблемы только во время выполнения (после того, как слишком поздно - например, возможно, после того, как оно было выпущено и запущено на компьютере конечного пользователя).В некоторых случаях может быть достаточно легко обнаружить «перекрывающиеся области» с помощью статического анализатора исходного кода, но эти случаи могут быть «легко обнаружены путем тестирования во время выполнения до выпуска программного обеспечения».

Для некоторых вещей (хитрые указатели, поврежденная куча) существуют инструменты (valgrind) для обнаружения проблем.К сожалению, они обнаруживают проблемы только тогда, когда они действительно возникают (и не обнаруживают проблем, которые не возникают во время тестирования, но случаются, когда программное обеспечение работает на компьютере конечного пользователя).

Для остальных (сбои ОСи аппаратные сбои), если вы не можете доверять ОС или оборудованию, то вы не можете предполагать, что любой код, который что-либо проверяет, будет работать правильно.

0 голосов
/ 22 января 2019

memcpy имеет предварительное условие, что области памяти не будут перекрываться.Вы вызываете неопределенное поведение , если нарушаете это предварительное условие.

Аналогично, вы также вызываете неопределенное поведение, если вы читаете за пределами исходного буфера или записываете за пределами целевого буфера.Это продиктовано стандартом.

Когда вы вызываете неопределенное поведение, вы не можете предсказать, как программа будет вести себя в будущем (или даже в прошлом).Это может привести к сбою, может привести к странным результатам или к нормальной работе.

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

...