Нарушение прав доступа при преобразовании из uint32_t в wchar_t и сохранении в wstring

Это может быть простой вопрос, но у меня есть значение в DirectXTDK, которое находится в uint32_t. Я хотел бы отобразить это, объединив его с wchar_t.

Это то, что у меня есть до сих пор -

char buffer[1];
wchar_t* ws1 = (wchar_t *)itoa(m_timer.GetFramesPerSecond(), buffer, 10), * ws2 = L" FPS";
std::wstring s(ws1);
s += std::wstring(ws2);
const wchar_t* fps = s.c_str();

// Draw Text to the screen
m_sprites->Begin();
    m_font->DrawString(m_sprites.get(), L"DirectX Museum Scene", XMFLOAT2(10, 10), Colors::Yellow);
    m_font->DrawString(m_sprites.get(), fps, XMFLOAT2(8, 30), Colors::Yellow);
m_sprites->End();

Проблема возникает при отображении FPS, когда пытаются отобразить мусорные символы, которые шрифт по умолчанию не может обработать. Без itoa выполнение вызовет исключение в std::wstring s(ws1).

Как я могу эффективно преобразовать uint32_t в wchar_t * для правильного отображения FPS? Спасибо!


person firepro20    schedule 25.11.2019    source источник
comment
Похоже, вы не выделяете достаточно большой буфер для преобразования itoa. Вам понадобится как минимум размер буфера 2, один для FPS (если это только одна десятичная цифра) и один для завершающего нулевого символа. Но более реалистично выяснить, каков ваш максимальный FPS, и выделить достаточно места для хранения такого количества цифр + 1. Еще лучше выделить 33 char в буфере для обработки чисел длиной до 32 бит.   -  person JohnFilleau    schedule 25.11.2019
comment
(wchar_t *)itoa -- Удалить слепок. Какую ошибку компилятора вы получаете? Внимательно прочтите эту ошибку — не скрывайте ее, выполняя приведение в стиле C. Со строками или строковыми типами вам следует редко, если вообще когда-либо, приводить такие вещи. Либо используйте правильные типы строк, чтобы вам не нужно было выполнять приведение типов, либо найдите правильные функции, использующие используемые вами типы строк.   -  person PaulMcKenzie    schedule 25.11.2019
comment
@John Вам не нужно 33 символа (32 десятичных цифры) для обработки чисел с представлением 32 бит. Максимально возможное число — 4 294 967 295, состоящее всего из 10 цифр.   -  person Lightness Races in Orbit    schedule 25.11.2019
comment
@LightnessRaceswithMonica, спасибо, вы правы. Я прочитал справочную страницу для itoa и просмотрел ту часть, где этот размер был предложен для основания = 2. Мозг пердеть на моем конце.   -  person JohnFilleau    schedule 25.11.2019
comment
@Джон: Хе-хе-хе :)   -  person Lightness Races in Orbit    schedule 25.11.2019
comment
@PaulMcKenzie Исключение по адресу 0x00007FFC105D2E3C (ucrtbased.dll) в DirectXTKSimpleSample_2015.exe: 0xC0000005: место чтения нарушения прав доступа 0x00000000000000000. произошло, когда я перешел на wchar_t* ws1 = (wchar_t *)(m_timer.GetFramesPerSecond())   -  person firepro20    schedule 25.11.2019
comment
@firepro20 firepro20 Это ошибка времени выполнения, а не ошибка компилятора. Когда вы компилируете код с удаленными приведениями, какую ошибку выдает вам компилятор? Почему ты бросил? По сути, вы сказали компилятору заткнуться, не выдавать мне ошибку, я знаю, что делаю, но, конечно, это не так. Пример: wchar_t* ws1 = itoa(m_timer.GetFramesPerSecond(), buffer, 10) -- Я уверен, что компилятор сказал бы вам, что это незаконно.   -  person PaulMcKenzie    schedule 25.11.2019
comment
@firepro20 Вам было приказано удалить приведение и прочитать полученную ошибку, а не удалять приведение, вызов функции и другие вещи.   -  person Lightness Races in Orbit    schedule 25.11.2019
comment
@lightness заработало, спасибо!   -  person firepro20    schedule 25.11.2019


Ответы (2)


itoa создает строку символов ASCII, а не широкую строку.

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

Меня также беспокоит ваш выбор размера буфера; Вы знаете, что в значении количества кадров в секунду будет только одна цифра? И где место для нулевого терминатора?

Я думаю, вы хотели _itow. Но чтобы решить проблему с буфером, _itow_s было бы лучше.

А еще лучше полностью отказаться от устаревших вещей и получить себе хороший std::to_wstring . ????

person Lightness Races in Orbit    schedule 25.11.2019

@Lightness Races с Моникой направили меня в правильном направлении :)

преобразован в wstring и работает как положено

//char buffer[11]; // 32 bits, 10 characters + 1 for terminating null character
    std::wstring ws1 = std::to_wstring(m_timer.GetFramesPerSecond());
    std::wstring ws2 = L" FPS";
    std::wstring s(ws1);
    s += std::wstring(ws2);
    const wchar_t* fps = s.c_str();

    // Draw Text to the screen
    m_sprites->Begin();
        m_font->DrawString(m_sprites.get(), L"DirectX Museum Scene", XMFLOAT2(10, 10), Colors::Yellow);
        m_font->DrawString(m_sprites.get(), fps, XMFLOAT2(8, 30), Colors::Yellow);
    m_sprites->End();
person firepro20    schedule 25.11.2019