Странная ситуация, связанная с char [] и memcpy

Я новичок в C ++ и просто пытаюсь написать некоторый код, чтобы сам поэкспериментировать.

Недавно я столкнулся с проблемой, которую не могу отладить.

char acExpReason[128];
char acReason[] = "An error message is information displayed when an unexpected condition occurs, usually on a computer or other device. On modern operating systems.";

memcpy(acExpReason, acReason, sizeof(acExpReason));
std::string strExpReason(acExpReason);

Я использую VS2005 для добавления точек останова к каждой строке для отладки.

когда он достигает точки останова во второй строке, имя переменной и информация о значении в Autos:

  • acReason 0x00f6f78c «ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ» char [147]

  • acExpReason 0x00f6f828 «ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ̺» char [128]

когда он достигает точки останова в третьей строке, информация об имени и значении переменной в Autos:

  • acExpReason 0x00f6f828 «ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ̺» char [128]

  • acReason 0x00f6f78c «Сообщение об ошибке — это информация, отображаемая при возникновении непредвиденного состояния, обычно на компьютере или другом устройстве. В современных операционных системах.» символ [147]

когда он достигает точки останова в четвертой строке, информация об имени и значении переменной в Autos:

  • acExpReason 0x00f6f828 «Сообщение об ошибке — это информация, отображаемая при возникновении непредвиденного состояния, обычно на компьютере или другом устройстве. На современном charº» char [128]

  • acReason 0x00f6f78c «Сообщение об ошибке — это информация, отображаемая при возникновении непредвиденного состояния, обычно на компьютере или другом устройстве. В современных операционных системах.» символ [147]

  • strExpReason Bad Ptr

после выполнения последней строки информация в Autos:

  • acExpReason 0x00f6f828 «Сообщение об ошибке — это информация, отображаемая при возникновении непредвиденного состояния, обычно на компьютере или другом устройстве. На современном charº» char [128]

  • acReason 0x00f6f78c «Сообщение об ошибке — это информация, отображаемая при возникновении непредвиденного состояния, обычно на компьютере или другом устройстве. В современных операционных системах.» символ [147]

  • strExpReason «Сообщение об ошибке — это информация, отображаемая при возникновении непредвиденного состояния, обычно на компьютере или другом устройстве. На современном компьютере»

в основном, мой код хочет просто иметь полную строку сообщения, которая хранится в acReason [], а также есть копия полного сообщения в фиксированной длине (здесь 128).

но я не знаю, почему acExpReason и strExpReason (строковая версия acExpReason) заканчиваются странными символами «ÌÌÌÌÌÌÌ̺», которые мне не нужны (так как я буду использовать эту строку для сравнения с другой строкой позже).

Я попытался использовать memcpy, strcpy и strncpy, и все они в итоге получили этот набор странных символов в конце строки.

Кто-нибудь может помочь?
Спасибо заранее.

0

Решение

В C все строковые функции, такие как strcpy, а также конструктор для c ++ std::string принимать char* в качестве параметра, кроме char* должен заканчиваться байтом, содержащим `\ 0`.

У acExpReason нет нуля, заканчивающего его, поэтому все строковые функции ищут следующий 0 байт в памяти. У acReason есть завершающий `\ 0`. Обычный strcpy будет работать, поскольку он также копирует 0, однако @VladLazarenko говорит, что размер буфера слишком мал, что приведет к перезаписи всей памяти.

Для работы memcpy вам нужно скопировать на один байт меньше буфера и сделать последний байт буфера 0.
например

memcpy(acExpReason, acReason, sizeof(acExpReason)-1);
acReason[sizeof(acExpReason)-1] = 0;
3

Другие решения

std::string strExpReason(acExpReason);

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

4

Вы также можете использовать string конструктор, который принимает диапазон итератора —

std::string strExpReason(acExpReason, acExpReason+sizeof(acExpReason));
2
По вопросам рекламы [email protected]