2015-12-01 3 views
0

Windows 7, Visual Studio 2015.Почему я получаю неправильный массив массива при использовании WideCharToMultiByte?

#ifdef UNICODE 
    char *buffer = NULL; 
    int iBuffSize = WideCharToMultiByte(CP_ACP, 0, result_msg.c_str(), 
     result_msg.size(), buffer, 0, NULL, NULL); 

    buffer = static_cast<char*>(malloc(iBuffSize)); 
    ZeroMemory(buffer, iBuffSize); 

    WideCharToMultiByte(CP_ACP, 0, result_msg.c_str(), 
     result_msg.size(), buffer, iBuffSize, NULL, NULL); 

    string result_msg2(buffer); 
    free(buffer); 

    throw runtime_error(result_msg2); 
#else 
    throw runtime_error(result_msg); 
#endif 

result_msg является std::wstring для Юникода и std::string для набора символов в многобайтовой.

многобайтовой набор символов:

enter image description here

Для Unicode набор символов:

enter image description here

+2

'зЬй :: строка :: size() 'возвращает количество символов, не считая нулевого терминатора. Когда вы конвертируете в Unicode, вы игнорируете нулевой терминатор. Целевая строка не заканчивается нулем, и когда вы конвертируете ее в строку, она просто забирает мусор. Используйте ['std :: string' c'tor] (https://msdn.microsoft.com/en-us/library/y22b7w38.aspx), который принимает аргумент с явной длиной. – IInspectable

+0

'std :: vector' следует отдавать предпочтение над malloc. Которое вы не должны использовать в C++ в любом случае. Вы должны использовать 'new' в C++. –

ответ

3

Указан размер входной строки как result_msg.size(), который не включает в себя завершающий нуль символ, и поэтому выход также не будет завершен нулем. Но когда вы конвертируете buffer в string, вы не указываете размер buffer, поэтому конструктор string ожидает нулевой терминатор. Без этого терминатора он захватывает данные из окружающей памяти до тех пор, пока не встретит нулевой байт (или не получит ошибку доступа к памяти).

Либо используйте result_msg.size() + 1 для размера ввода, либо укажите -1 в качестве входного размера, чтобы WideCharToMultiByte() определял размер ввода автоматически. Любой подход будет включать нулевой ограничитель в выходе.

Или, продолжайте использовать result_msg.size() сек размер входного и использовать значение iBuffSize при преобразовании buffer в string, то вам не нужен нулевой терминатор:

string result_msg2(buffer, iBuffSize); 
+0

Я не знаю, как 'wstring' и' string' держат их valus, поэтому я буду использовать '++ iBuffSize;' вместо '-1'. Спасибо. –

+0

Нет. Используйте -1. 'c_str()' имеет значение null. Дальше, не зацикливайтесь на операторах инкремента. Если -1 не был доступен, вы должны передать 'iBuffSize + 1', чтобы избежать изменения значения' iBuffSize'. –