C++, Wrapper function for sprintf_s
包括banned.h(Microsoft安全工具之一)后,编译器警告我sprintf()函数不安全,并且MSDN中心向我建议使用sprintf_s,因为我的项目是跨平台的,我为sprintf函数编写了一个包装器。
1 2 3 4 5 6 7 8 9
| //safe function for sprintf();
void WrapperSprintf( char *buffer, const char *format, ... )
{
#ifdef _WIN32
sprintf_s(buffer, sizeof(buffer), format,...);
#else
sprintf(buffer, format, ...);
#endif
} |
在行sprintf_s(buffer, sizeof(buffer), format,...);
上给我一个错误
error C2059: syntax error : '...'
任何人都知道如何为sprintf_s()编写包装函数吗?
非常感谢。
- sizeof(buffer)并没有达到您的期望,它的输出始终与sizeof(char*)相同。
-
这是使用宏的有效案例。 #define my_sprintf sprintf
-
如果使用stringstream,则可以完全放弃sprintf。
-
Microsoft添加的所有这些xxx_s函数都有一个新的且非常重要的参数:max_size。某些不带重载的情况可以不带重载而使用固定数组(例如template <size_t N> int sprintf_s(char [N] buffer,...),它调用sprintf_s(char * butter,size_t N,...)...等)。这是strnlen vs. strlen的一种模式。因此,您应该更改代码并始终在非Windows平台中传递\\'max size \\'参数并忽略它,或者在Windows平台中传递一些预定义的max_size(如1028)。
-
@?€???????±á?¥?μá?–感谢您指出:)
...不会神奇地将函数声明转换为使用这些参数的其他调用。您必须包括可变参数的东西,并使用它来调用下一层。
步骤基本上是:
-
包括stdarg标头。
-
声明va_list。
-
呼叫va_start。
-
调用v*printf函数之一。
-
呼叫va_end。
例如,这是一个小程序,演示如何提供一个将格式化的输出写入字符串的野兽,类似于您看上去的样子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <stdio.h>
#include <stdarg.h>
void x (char *buf, char *fmt, ...) {
va_list va;
va_start (va, fmt);
vsprintf (buf, fmt, va);
va_end (va);
}
int main (void) {
char buff[100];
x (buff,"Hello, %s, aged %d","Pax", 40);
printf ("%s\
", buff);
return 0;
} |
我,我倾向于忽略Microsoft关于sprintf不安全的建议。如果您不知道自己在做什么,那对任何工具都可以说是不安全的。如果您想成为一名优秀的C程序员,您将学习该语言的局限性和缺点。
包括在char*上使用sizeof的那个,期望它返回它指向的缓冲区的大小,而不是指针的大小:-)
但是,如果您想成为C开发人员,请成为C开发人员。尽管C和C具有许多共同点,但它们不是同一语言。 C主要包含很多C东西,因此您(大部分)可以采用已经编写的C代码并将其用于C应用程序中。
换句话说,如果它是C应用程序,请使用std::string和std::stringstream(a)而不是char数组和s*printf调用。
您应该编写C代码,就像C位不存在一样。否则,您更像是C程序员而不是C程序员:-)
(a)当然,知识渊博的开发人员可能已经避开了stringstream内容固有的冗长性,并使用了fmtlib之类的东西(具有printf的简洁性,但类型安全性C开发者来欣赏)。
尤其是因为它已被购买到C 20中,它将成为基础的一部分,所有人都可以使用。
- 谢谢,paxdiablo,您的评论非常好并且很有帮助。
-
"只有在不知道自己在做什么的情况下才是不安全的"是事实,但是当您认为sizeof(buffer)返回缓冲区的大小时,可悲的是意味着"不知道自己在做什么"。 C格式化方法虽然需要更多工作,但可以避免错误使用sprintf时可能发生的许多严重丑陋的事情。 C是不能原谅的,但是C对看似很小的错误的容忍度甚至更低。
-
可悲的是,默认情况下必须弃用这些功能的原因是,许多开发人员不知道他们在做什么,并编写了损坏的代码。
-
sprintf是不安全的!仅仅因为MS提供了它并不能使其变得可忽略。它在模板和SAL之上运行-它们在编译和代码分析时检测到大多数错误。
-
如果您知道自己在做什么,那并不是不安全的!如果您确保缓冲区足够大以容纳格式字符串可以生成的最大内容,则它与任何事物一样安全。当您输入错误的长度时,它甚至比使用"安全"变体更安全:-)您仍然必须知道如何正确使用所谓的安全变体,与知道如何使用其他变体几乎没有什么不同。