编写代码是否有任何错误:
char* sp=(char*)malloc(128);
int x=22;
wsprintf(sp,"%d",x);
cout<<sp;
我特意问安全错误?
答案 0 :(得分:3)
这里有许多“潜在的”问题,其中没有任何问题实际上是在发生任何事情,但你可能会发现事情并不像你期望的那样。
首先:wsprintf,作为Win32 API(http://msdn.microsoft.com/en-us/library/windows/desktop/ms647550(v=vs.85).aspx)原型为:
int __cdecl wsprintf(
_Out_ LPTSTR lpOut,
_In_ LPCTSTR lpFmt,
_In_ ...
);
其中LPTSTR
被定义为char*
或wchar_t*
,具体取决于UNICODE
符号的定义与否(检查您的项目设置和/或构建命令)
现在,如果您使用ANSI构建(没有UNICODE),则所有类型都是连贯的,但是没有检查wsprintf写入的内容超过您分配的128个字符。如果你只是写一个十进制整数就没有问题,但如果你(后面的其他人)稍后修改“消息”并且没有进行检查,可能会出现一些意外(如wsprintf(sp,"This is the number I've been told I was supposed to be expected to be: %d",x);
这仍然适合128个字符?!?)
如果您使用UNICODE构建,则分配128个char,并在其上写入双字节字符串。数字22将写为\x32\x00\x32\x00\x00\x00
(3200是0x0032的小端编码,即对应于UNICODE 50的wchar_t代表'2')。
如果你将该序列赋予cout(基于char,而不是基于wchar_t)将第一个\ x00视为字符串终止符,并将输出...只是'2'。
要保持连贯,你要么:
char
的类型和功能(OK malloc和cout,但wsprintfA
代替wsprintf
)wchar_t
的类型和函数(malloc(128 * sizeof(wchar_t)),wchar_t *和wsprintfW
)TCHAR
的类型(malloc(128 * sizeof(TCHAR)),TCHAR *和wsprintf,但根据UNICODE将tcout
定义为cout
或wcout
)。答案 1 :(得分:1)
没有安全性错误,因为转换为C字符串的int永远不会超过您分配的大小。
然而,这种编程风格具有潜力以解决安全问题。历史证明,这种代码一次又一次地引起了真正的安全问题。那么也许你应该学习更好的编码风格?
答案 2 :(得分:0)
好的,假设您已声明使用的是winapi,请从他们的documentation中阅读:
注意不要使用。请考虑使用以下功能之一 而是:StringCbPrintf,StringCbPrintfEx,StringCchPrintf或 StringCchPrintfEx。请参阅安全注意事项。
因此请勿使用。但是我会忽略他们告诉你的事情,而是:
用C语言编写,以及C标准库(sprintf,snprintf等)中的函数。在这种情况下,你不能使用cout。
用C ++编写。使用std :: string,甚至还有一个新的to_string,以及boost :: format和ostringstream来帮助你构建格式化的字符串。你仍然可以在那里使用C标准库函数,如果你想更好地适合你的目的,但是将分配内容留给库。
答案 3 :(得分:0)
This MSDN link列出了对使用wsprintf
的一些担忧。它们似乎不适用于您的示例,但它们确实提供了一些您可能想要探索的替代方案。