Итоа и разные наборы символов C++ visual studio 2013
Мой код:
m_ListCtrlCandidates.InsertItem(i, _itoa_s(candidate[i].ID, (char*)(LPCTSTR)str, 10));
m_ListCtrlCandidates.SetItemText(i, 1, _itoa(candidate[i].FingerNumber, (char*)(LPCTSTR)str, 10));
m_ListCtrlCandidates.SetItemText(i, 2, _itoa(candidate[i].SampleNumber, (char*)(LPCTSTR)str, 10));
m_ListCtrlCandidates.SetItemText(i, 3, _itoa(candidate[i].ConfidenceLevel, (char*)(LPCTSTR)str, 10));
Ошибка:
Error 2 error C4996: '_itoa': This function or variable may be unsafe. Consider using _itoa_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. d:\documents\visual studio 2013\projects\gatekeeper\gatekeeper\gatekeeperdlg.cpp 416 1 Gatekeeper
Я использую SDK, который имеет следующий код в их примере. Это добавляет потенциальные совпадения в список в диалоге. Первоначально я установил в свой проект Unicode и обновил код для работы. Это доставляло мне неприятности, поэтому я посмотрел пример кода, и его набор символов был пустым. Так что я изменил свой, и теперь я получаю эту ошибку.
Если я переключаю его на _itoa_s, я получаю ошибку, что функция не принимает 3 аргумента. Поэтому я предполагаю, что мне не хватает аргумента размера, но я не уверен, какой он должен быть. Кроме того, он прекрасно компилируется в их примере кода, если оставить его как _itoa.
Я бы очень хотел сохранить его в Unicode. Использование _wtoi вместо atoi помогло в других местах. Есть ли что-то подобное для этого случая?
1 ответ
Я использую SDK, который имеет следующий код в их примере.
Это прискорбно!
_itoa (кандидат [я]. ФингерНомер, (символ *)(LPCTSTR) ул., 10)
Я предполагаю, что вы используете MFC, str
это CString
и ты звонишь CListCtrl::SetItemText
,
(LPCTSTR)
оператор на CString
получает указатель на базовый буфер, содержащий строковые данные. Это const TCHAR*
, так что если вы компилируете в режиме ANSI, это const char*
указатель на байты; в режиме Юникод это const wchar_t*
указывают на 16-битные единицы кода.
Приведение этого к неконстантному char*
и спрашивать _itoa
писать на это довольно плохая идея. Это переписывает все, что было изначально в CString
и если число достаточно велико, чтобы результирующая строка была длиннее, чем изначально CString
Вы можете записывать поверх конца массива, что может привести к повреждению памяти.
Приведение к char*
в режиме Unicode еще более странно, так как вы используете wchar_t
массив как хранилище для char*
байт. А также SetItemText()
в режиме Unicode будет ожидать получить wchar_t
персонажи вместо этого наверняка?
Использование _wtoi вместо atoi помогло в других местах. Есть ли что-то подобное
_itow
существует как wchar_t
аналог _itoa
, (По крайней мере, в VS. Ни одна из функций не является стандартной C[++] как таковой.)
Вы можете включить #ifdef _UNICODE
и позвоните либо _itoa
или же _itow
соответствовать любому типу TCHAR
является. Но если вам действительно не нужно поддерживать древнюю сборку только для ANSI по какой-то устаревшей причине, то нет особых причин для беспокойства TCHAR
переключение в эти дни. Вы можете просто придерживаться режима Юникод и использовать wchar_t
строки для текста.
ошибка C4996: '_itoa': эта функция или переменная может быть небезопасной.
Microsoft отказалась от ряда функций C, которые записывают переменные объемы содержимого в заранее выделенные буферы, потому что буферы могут быть слишком короткими, что приводит к вышеупомянутому ужасу повреждения памяти. В прошлом это было причиной множества проблем с безопасностью в приложениях, поэтому лучше избегать этого.
К сожалению, предупреждение 4996 фактически не поддерживает некоторые стандартные функции, которые тоже не очень опасны, что довольно утомительно, особенно если учесть, что _s
версии, предлагаемые в качестве замены, обычно не поддерживаются другими компиляторами.
В этом случае, хотя MS вроде как, _itoa
не совсем безопасно. Чтобы использовать его безопасно, вам нужно выделить достаточно большой буфер для максимально длинного целого числа передаваемого вами типа, и это действительно легко сделать неправильно.
Если я переключаю его на _itoa_s, я получаю ошибку, что функция не принимает 3 аргумента. Итак, я предполагаю, что мне не хватает аргумента размера, но я не уверен, какой размер он должен быть
Однако в конце указателя доступно множество элементов для записи. Так что в настоящее время это будет зависеть от длины CString
чей буфер ты крадешь. Но это не очень хорошая идея. Вы можете выделить свой собственный буфер:
wchar_t str[8];
_itow_s(candidate[i].FingerNumber, str, 8, 10);
Это безопасно, хотя все равно не удается (с ошибкой EINVAL
) если FingerNumber имеет более 7 цифр, так как не было бы места для их хранения (включая \0
терминатор).
Функции как itoa
что запись содержимого переменной в буферы в общем довольно уродливая. Если вы можете использовать современный C++ с STL, есть более простые и безопасные методы обработки строк, например:
#include <string>
std::wstring fingers = std::to_wstring(candidate[i].FingerNumber);
m_ListCtrlCandidates.SetItemText(i, 1, fingers.c_str());
(хотя насколько хорошо это будет сочетаться с MFC старой школы и CString - другой вопрос.)