Можно попробовать следующее:
Редактирование: Nprof был заменен SlimTune и работы с приложениями.Net 4.0
Что мешает мне записать в ячейку памяти больше 81 единицы?
Ничего. Однако это приводит к неопределенному поведению . Это означает, что угодно может случиться, и вы не должны зависеть от того, что он делает одно и то же дважды. В 99,999% случаев это ошибка.
Что я могу сделать, чтобы предотвратить это?
Всегда проверяйте, находятся ли ваши указатели в заданных пределах, прежде чем обращаться к ним (читать или писать в них). При переходе к строковым функциям всегда убедитесь, что строки заканчиваются на \ 0
.
Вы можете использовать инструменты отладки, такие как valgrind, чтобы помочь вам в обнаружении ошибок, связанных с указателем за пределами границ и доступом к массиву. 1252] подход stdlib
Для вашего кода вы можете использовать utstrncat
, который действует как utstrcat
, но принимает максимальный размер (т.е. размер буфера).
Вы также можете создать массив struct / class или использовать std :: string
в C ++. Например:
typedef struct UtString {
size_t buffer_size;
char *buffer;
} UtString;
Тогда пусть ваши функции будут работать с этим. Вы даже можете выполнить динамическое перераспределение, используя этот метод (но, похоже, это не то, что вам нужно).
Другой подход - иметь конец буфера ], аналогичный маркеру конца строки . Когда вы встретите маркер, не пишите в это место или на один перед ним (для маркера конца строки) (или вы можете перераспределить буфер, чтобы было больше места).
Например, если у вас есть "hello world \ 0xxxxxx \ 1"
в виде строки (где \ 0
- это маркер конца строки, \ 1
- маркер конца буфера, а x
- случайные данные). добавление «это весело»
будет выглядеть следующим образом:
hello world\0xxxxxx\1
hello world \0xxxxx\1
hello world t\0xxxx\1
hello world th\0xxx\1
hello world thi\0xx\1
hello world this\0x\1
hello world this \0\1
*STOP WRITING* (next bytes are end of string then end of buffer)
Проблема с вашим кодом здесь:
if ((i+j-1) == 20)
return s;
Хотя вы останавливаетесь перед переполнением буфера, вы не отмечаете конец строки.
Вместо возврата вы можете использовать break
для преждевременного завершения цикла for
. Это приведет к запуску кода после цикла for
. Это устанавливает маркер конца строки и возвращает строку, которую вы хотите.
Кроме того, я боюсь, что в вашем распределении может быть ошибка. У вас есть + 1
, чтобы выделить размер перед строкой, верно? Возникла проблема: unsigned
обычно не 1 символ; для этого вам понадобится + sizeof (unsigned)
.
Ничто не мешает вам писать сверх этого предела, и то, что происходит, зависит от того, что выходит за эти рамки. Стандартный хакерский трюк (переполнение буфера) для взлома программ, которые не проверяют и не гарантируют, что они не перезаписывают ограничения буфера.
Как упоминалось в других плакатах, вам просто нужно тщательно программировать. Не используйте такие вызовы, как strlen, strcpy - используйте ограниченные по длине версии, такие как strncpy и т. Д.
Ничто не мешает вам это сделать. Если вы так сделаете, может случиться что угодно: программа может продолжить свой веселый путь, как будто ничего не произошло, она может вылететь сейчас, она может вылететь позже, она может даже стереть ваш жесткий диск. Это область неопределенного поведения .
Существует ряд инструментов, которые пытаются обнаружить или смягчить эти типы проблем, но нет ничего надежного. Одним из таких инструментов является valgrind . valgrind наблюдает за схемой доступа к памяти вашей программы и уведомляет вас о подобных проблемах. Он делает это, выполняя вашу программу на своего рода виртуальной машине, поэтому это значительно снижает производительность вашей программы, но при правильном использовании может помочь вам отловить множество ошибок.
Карл предлагает strncpy () , что является началом в правильном направлении. Основная идея состоит в том, чтобы выработать привычку избегать переполнения буфера, применяя определенные методы. Более продуманная библиотека для этого описана в strlcpy и strlcat - Consistent, Safe, String Copy and Concatenation .
Что происходит: ничего, или ваша программа получит SIGSEGV брошен на это. Что вам следует делать: Тщательно напишите свою программу. Используйте такие инструменты, как valgrind.