使用带有malloc的wsprintf

时间:2012-10-31 11:50:59

标签: c++ c string winapi

编写代码是否有任何错误:

char* sp=(char*)malloc(128);
int x=22;

wsprintf(sp,"%d",x);
cout<<sp;

我特意问安全错误?

4 个答案:

答案 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定义为coutwcout )。

答案 1 :(得分:1)

没有安全性错误,因为转换为C字符串的int永远不会超过您分配的大小。

然而,这种编程风格具有潜力以解决安全问题。历史证明,这种代码一次又一次地引起了真正的安全问题。那么也许你应该学习更好的编码风格?

答案 2 :(得分:0)

好的,假设您已声明使用的是winapi,请从他们的documentation中阅读:

  

注意不要使用。请考虑使用以下功能之一   而是:StringCbPrintf,StringCbPrintfEx,StringCchPrintf或   StringCchPrintfEx。请参阅安全注意事项。

因此请勿使用。但是我会忽略他们告诉你的事情,而是:

  1. 用C语言编写,以及C标准库(sprintf,snprintf等)中的函数。在这种情况下,你不能使用cout。

  2. 用C ++编写。使用std :: string,甚至还有一个新的to_string,以及boost :: format和ostringstream来帮助你构建格式化的字符串。你仍然可以在那里使用C标准库函数,如果你想更好地适合你的目的,但是将分配内容留给库。

答案 3 :(得分:0)

This MSDN link列出了对使用wsprintf的一些担忧。它们似乎不适用于您的示例,但它们确实提供了一些您可能想要探索的替代方案。