Неправильное поведение массивов символов после strncpy - PullRequest
0 голосов
/ 18 февраля 2020

Я не C -dev и могу что-то не так (я делаю изменения в старом коде):

Существует функция с именем strncpySafe (это просто оболочка на strncpy как я вижу):

void    strncpySafe(char *strDest, const char *strSource, int count)
{
    strncpy(strDest, strSource, count-1);
    strDest[count-1] = '\0';
}

Шаг сам по себе, где находится копия из источника A в источник B со смещением:

void Foo(const char *message) {
char line[1024];
...
strncpySafe(line, &message[message_offset], count);

В последнем на шаге они изменяют скопированный line[] (message[] должен остаться прежним):

line[N] = 0;

На последнем шаге я вижу из отладчика VSCode, что line[N] изменяется и в то же время message[N] также модифицируется.
Я использую Ubuntu /g++-8, -march=x86-64, -std=c++11.
Это что-то о тех же указателях? Это неправильное использование strncpy?
Спасибо.

ps: тот же код используется в игровом клиенте для windows и linux, и я могу сказать, что на windows он не воспроизводится (windows был построен на более старом c -компиляторе, еще не проверял с той же сборкой c ++ 11).

EDIT : to поясните, что модификация line и message происходит в то же время, когда я пропускаю шаг с line[N] = 0;

. Удалено неправильное именование message_offset_2. Это count.
Позвольте мне привести пример выполнения:

strncpySafe(line, &message[5], 10); // It copies 10 elements from 5th
line[5] = 0; // this leads that message[5] also gets 0 for it's element

Нет ошибок с границами (смещения и счетчики кажутся в порядке).

I согласитесь, что этот код устарел, и лог c может быть неясным (почему это так), и я мог бы использовать std::string. Для меня было интересно, почему это происходит.

1 Ответ

1 голос
/ 18 февраля 2020

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

Например, третий параметр, который вы назвали как message_offset_2, указывает количество символов, которые должны быть скопированы из строки в целевой массив символов. Поэтому его не следует называть message_offset_2.

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

Таким образом, либо третий аргумент указан неверно, либо имеет место перекрытие массивов символов.

Но в любом если функция объявлена ​​и определена неверно.

Если это обертка вокруг стандартной C функции strncpy, то она должна быть объявлена ​​как минимум как

char * strncpySafe( char * restrict s1, const char * restrict s2, size_t n );

Или, если она объявляется как функция C ++, тогда

char * strncpySafe( char * s1, const char * s2, size_t n );

Если функция предназначена для копирования n символов, тогда тело функции должно выглядеть как

if ( n )
{
    strncpy( s1, s2, n );
    s1[n] = '\0';
}

return s1;

Таким образом, целевой массив должен иметь как минимум n + 1 элементов.

And (C Standard, 7.23.2.4 функция strncpy)

Если копирование происходит между объектами, которые перекрываются, поведение undefined.

...