RELEASE上的bug但不是DEBUG上的bug

时间:2011-07-25 18:00:47

标签: c++ visual-studio-2010

std::string s("foo");
sprintf(buf,"%s",s);

为什么至少在MSVC 2010下这行代码在DEBUG中没有错误,但在RELEASE中有错误?

5 个答案:

答案 0 :(得分:9)

%s格式说明符期望NULL终止char*。您正在传递std::string个实例。如果它在DEBUG中有效,那只是纯粹的运气。

您应该使用:

std::string s("foo");
sprintf(buf, "%s", s.c_str());

这将提取char*并确保缓冲区以NULL结尾。

在运行时库std::string中可能有不同的DEBUG和RELEASE实现。尝试使用这两种设置进行编译,但是将调试符号添加到RELEASE构建中,然后逐步执行代码。查看存储s的内存位置。有什么不同吗?

答案 1 :(得分:4)

sprintf()这样的变量函数不是严格类型安全的,因为任何参数类型都被接受(在编译时)作为可变参数集的一部分。

正如其他答案所示,"%s"是一个格式说明符,需要NULL终止的字符串。在这种情况下传递std :: string可能是未定义的。

如果它在DEBUG模式下工作,它可能只是“幸运”,因为实现恰好打印了正确的结果(可能源于std :: string对象的c样式转换为字符指针)。 / p>

答案 2 :(得分:3)

那应该不行。你可能会遇到未定义的行为。

std::string s("foo");
sprintf(buf,"%s",s.c_str());

您实际上可能正在使用流。

答案 3 :(得分:2)

那是错的。你应该这样写:

std::string s("foo");
sprintf(buf,"%s",s.c_str());

std::string类型的对象无法传递给sprintf,因为没有格式说明符对应std::string。此外,%s期望对象类型为char*char[]c_str()函数返回char*,因此上述方法可行。

答案 4 :(得分:0)

如果你打算混淆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 ++中太容易了,但我们可以搞砸了。