什么是StringCbprintf,这与一般的sprintf有什么不同?

时间:2012-11-07 11:48:43

标签: c++ c windows winapi printf

我正在阅读以前编写的代码,并找到了StringCbPrintf()函数

我在msdn网站上发现了这样的声明:

HRESULT StringCbPrintf(
  _Out_  LPTSTR pszDest,
  _In_   size_t cbDest,
  _In_   LPCTSTR pszFormat,
  _In_    ...
);

这里的_in__out_是什么?

为什么在我们已经有sprintf()时需要它?

3 个答案:

答案 0 :(得分:8)

_In__Out_注意:既没有_in_/_out _也没有__In__/__Out__ _,也没有带有双重下划线的/analyze,正如其他人写的那样回答)所谓的 SAL注释。它们可以与<strsafe.h>编译器选项一起使用,并且可以帮助识别缓冲区溢出等错误和问题,以及原始C缓冲区和指针。除了MSDN documentation on SAL之外,您还可以阅读此blog post

有人讽刺地(并且错误地)写道:

  

“在世界其他地方,输入是常量指针,但我猜是这样   太简单了。 :)“

错过了SAL比更强大的事实。事实上,使用SAL,您还可以指定目标缓冲区的最大大小,指示哪个参数包含目标缓冲区大小;例如如果您打开StringCbPrintfW标题,您可以读到用于StringCbPrintfSTRSAFEAPI StringCbPrintfW( __out_bcount(cbDest) STRSAFE_LPWSTR pszDest, __in size_t cbDest, __in __format_string STRSAFE_LPCWSTR pszFormat, ...) { .... 的Unicode版本)的实际SAL注释是这样的:

__out_bcount(cbDest)

注意应用于pszDest参数的__out SAL注释如何指定这是指向输出缓冲区(_bcount)的指针,其中 size 由参数cbDest表示,以字节为单位const)。正如您所看到的,这是一个丰富的注释(比简单的“const”或“非std::vector”更丰富。)

在我看来,如果用可靠的容器类(例如std::stringStringCbPrintf)编写C ++代码,那么SAL就没用了,这些容器类知道它们自己的大小等等。但SAL在C-中很有用。带有原始指针的代码(如几个Win32 API)。

关于问题的第二部分:

  

“如果我们已经sprintf

,我们为什么需要sprintf

主要原因是StringCbPrintf不安全和缓冲区溢出功能;而是使用{{1}},您必须指定目标缓冲区的最大大小,这有助于防止缓冲区溢出(这是安全的敌人)。

答案 1 :(得分:2)

The documentation试图为您解释:

  

与它替换的函数相比,StringCbPrintf提供了额外的处理   代码中适当的缓冲区处理。缓冲区处理涉及缓冲区溢出的许多安全问题。 StringCbPrintf始终为null - 终止非零长度的目标缓冲区。

Microsoft API中使用__In____Out__修饰符:s表示如何使用指针参数。在世界其他地方,输入是const指针,但我想这太简单了。 :)

答案 2 :(得分:2)

据说here

  

StringCbPrintf是以下功能的替代品:

     
      
  • sprintf,swprintf,_stprintf
  •   
  • wsprintf
  •   
  • wnsprintf
  •   
  • _snprintf,_snwprintf,_sntprintf
  •   

因此,它不仅会替换sprintf,还会替换为wchar使用的_in_。它还引入了额外的缓冲区处理以防止缓冲区溢出(如同一篇msdn文章中所述)。它还始终 null - 终止目标缓冲区。 _out_#define用于显示哪些参数是输入参数,哪些参数是输出参数。那些很可能{{1}} d什么都没有,并且在编译开始之前就消失了。