[英]bug on RELEASE but not on DEBUG
std::string s("foo");
sprintf(buf,"%s",s);
为什么至少在MSVC 2010下,此行代码不会在DEBUG中出错,而在RELEASE中出错?
%s
格式说明符期望以NULL结尾的char*
。 您正在传递一个std::string
实例。 如果它在DEBUG中有效,那就太幸运了。
您应该使用:
std::string s("foo");
sprintf(buf, "%s", s.c_str());
这将提取一个char*
并确保缓冲区以NULL终止。
在运行时库中, std::string
可能对DEBUG和RELEASE具有不同的实现。 尝试使用这两种设置进行编译,但是将调试符号添加到RELEASE构建中,然后逐步执行代码。 查看存储s
的存储位置。 有什么区别吗?
像sprintf()
这样的可变参数函数并不是严格类型安全的,因为(在编译时)任何可变参数类型都可以作为可变参数集的一部分被接受。
如其他答案所示, "%s"
是一种格式说明符,期望以NULL
结尾的字符串。 在这种情况下,传递std :: string可能是不确定的。
如果它在DEBUG模式下工作,则很可能是“幸运的”,因为该实现恰好会打印正确的结果(可能源于std :: string对象的c样式强制转换为字符指针)。
那不行 很可能是您遇到未定义的行为。
std::string s("foo");
sprintf(buf,"%s",s.c_str());
实际上,您实际上应该使用流。
那是错的。 您应该这样写:
std::string s("foo");
sprintf(buf,"%s",s.c_str());
无法将类型为std::string
的对象传递给sprintf
因为没有格式说明符对应于std::string
。 此外, %s
期望使用char*
或char[]
类型的对象,并且c_str()
函数返回char*
,因此上述方法可以正常工作。
如果要混合使用c和c ++,则(出于性能原因,基于您的评论),将函数包装在c ++中以避免这些细微的错误是个好主意。
struct console_out
{
static void
print(const string& s)
{
sprintf(buf, "%s", s.c_str());
}
//other overloads should you want them
}
请小心一次,然后让编译器小心。
有时我认为这样的错误在c和c ++中太容易了,但是我们可以解决。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.