strcpy, когда буфер dest меньшего размера, чем буфер src

select author_name,dewey_number,Num_of_occur
from author a,(select author_id,dewey_number,count(dewey_number) Num_of_occur
                from   book
                group by author_id,dewey_number
                having count(dewey_number) > 1) dup
where a.author_id = dup.author_id
5
задан Tim Post 22 October 2009 в 01:23
поделиться

7 ответов

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

Более сложный ответ связан с изучение конкретной структуры памяти в вашей системе и того, как strcpy () работает внутри. Вероятно, это выглядит примерно так:

     N+28 "g0PP"
     N+24 "trin"
     N+20 "ng s"
     N+16 "a lo"
     N+12 " is "
src  N+08 "this"
     N+04 "DPPP"
dest N+00 "DDDD"

Буквы D обозначают байты в dest, буквы P - это байты заполнения, символы 0 - это ASCII NUL символы, используемые в качестве терминаторов строки.

Теперь strcpy (dest, src) несколько изменит содержимое памяти (при условии, что он правильно обрабатывает перекрывающиеся области памяти):

     N+28 "g0PP"
     N+24 "trin"
     N+20 "g0 s"
     N+16 "trin"
     N+12 "ng s"
src  N+08 "a lo"
     N+04 " is "
dest N+00 "this"

Т.е. в то время как dest теперь "содержит" полную строку ", это длинная строка »(если считать переполненную память),

11
ответ дан 18 December 2019 в 07:30
поделиться

Это переполнение буфера и неопределенное поведение.

В вашем случае похоже, что компилятор разместил dest и src последовательно в памяти. Когда вы копируете из src в dest , он продолжает копирование после конца dest и перезаписывает часть src .

7
ответ дан 18 December 2019 в 07:30
поделиться

с большой вероятностью строка является точным соседом. Так что в вашем случае у вас может быть это изображение

dst | | | | | src | | | | | |

так что вы начинаете писать, и случается, что поля src перезаписываются.

Но вы, конечно, не можете полагаться на это. Может случиться все, что у вас - неопределенное поведение. Так что что-то еще может случиться на другом компьютере в другой раз и / или другие варианты.

С уважением Фридрих

1
ответ дан 18 December 2019 в 07:30
поделиться

Ваш код вызвал переполнение буфера - копирование в dest больше символов, чем он может вместить. Дополнительные символы были записаны в другом месте стека, в вашем случае, где src указывал на.

Вам нужно использовать функцию strncpy () .

1
ответ дан 18 December 2019 в 07:30
поделиться

В качестве дополнительного примечания имейте в виду, что функция strncpy не подходит для использования, когда вам нужно выполнить копирование с защитой от переполнения буфера. Эта функция не предназначена для этой цели и никогда не предназначалась для этой цели. strncpy - это функция, которая была создана давным-давно для выполнения некоторого очень специфичного для приложения копирования строк в некоторой очень специфической файловой системе в какой-то старой версии UNIX. К сожалению, авторам библиотеки удалось «украсть» общее название strncpy , чтобы использовать его для этой очень узкой и конкретной цели. Затем он был сохранен в целях обратной совместимости. И теперь у нас есть поколение или два программиста, которые делают свои предположения о strncpy ' s цель, основанная исключительно на его названии, и, следовательно, использовать его ненадлежащим образом. На самом деле, strncpy имеет очень мало или вообще не имеет смысла.

Стандартная библиотека C (по крайней мере, ее версия C89 / 90) не предлагает функции копирования строк с защитой от переполнения буфера. Чтобы выполнить такое защищенное копирование, вы должны использовать либо какую-нибудь специфичную для платформы функцию, например strlcpy , strcpy_s , либо написать ее самостоятельно.

PS Это ] thread на StackOverflow содержит хорошее обсуждение реальной цели strncpy . См. Этот пост специально для точного объяснения его роли в файловой системе UNIX. Также см. здесь , где вы найдете хорошую статью о том, как появился strncpy .

И снова, strncpy - это функция для копирования совершенно другого типа строки - строки фиксированной длины. Он даже не предназначен для использования с традиционными строками с завершающим нулем в стиле C.

1
ответ дан 18 December 2019 в 07:30
поделиться

Либо я неправильно понимаю ваш вопрос, либо вы неправильно понимаете strcpy:

ВОПРОС: Я не понимаю, как исходный код был изменен. Согласно объяснение, strcpy следует сохранить копирование, пока не встретит '\ 0', поэтому да, но почему строка "src" попала изменено.

Мне кажется, вы ожидаете, что strcpy прекратит копирование в dest, когда он достигнет конца dest, на основании символа \ 0 . Это не то, что он делает. strcpy копирует в место назначения, пока не достигнет конца исходной строки, разделенной символом \ 0 . Предполагается, что вы выделили достаточно памяти для копии. Перед копированием в целевом буфере могло быть что угодно, включая все нули.

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

0
ответ дан 18 December 2019 в 07:30
поделиться

Я предлагаю быстро прочитать:

http://en.wikipedia.org/wiki/Strncpy#strncpy

, где показаны различия. По сути, strncpy позволяет указать количество байтов для копирования, что означает, что результирующая строка не обязательно завершается нулем.

Теперь, когда вы используете strcpy для копирования одной строки поверх другой, она не проверяет результирующую область памяти, чтобы увидеть если он достаточно большой - в этом плане он вас не держит. Он проверяет нулевой символ в строке src.

Конечно, dst в этом примере составляет всего 5 байтов. Так что же происходит? Он продолжает писать до конца dest и далее в памяти. И в этом случае следующая часть памяти в стеке - это ваша строка src. Итак, хотя ваш код не копирует его намеренно,

0
ответ дан 18 December 2019 в 07:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: