简体   繁体   English

发布时出现错误,但调试失败

[英]bug on RELEASE but not on DEBUG

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

Why at least under MSVC 2010 this line of code doesn't bug in DEBUG, but bug in RELEASE ? 为什么至少在MSVC 2010下,此行代码不会在DEBUG中出错,而在RELEASE中出错?

The %s format specifier expects a NULL terminated char* . %s格式说明符期望以NULL结尾的char* You are passing in a std::string instance. 您正在传递一个std::string实例。 If it works in DEBUG, that's just pure luck. 如果它在DEBUG中有效,那就太幸运了。

You should use: 您应该使用:

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

This will extract a char* and ensure that the buffer is NULL terminated. 这将提取一个char*并确保缓冲区以NULL终止。

It is possible that in the runtime library std::string has different implementations for DEBUG and RELEASE. 在运行时库中, std::string可能对DEBUG和RELEASE具有不同的实现。 Try compiling using both settings, but adding debug symbols to the RELEASE build and then step through the code. 尝试使用这两种设置进行编译,但是将调试符号添加到RELEASE构建中,然后逐步执行代码。 Look at the memory location where s is stored. 查看存储s的存储位置。 Is there any difference? 有什么区别吗?

Variadic functions like sprintf() are not strictly type safe, in that any argument type is accepted (at compile time) as part of the variadic argument set. sprintf()这样的可变参数函数并不是严格类型安全的,因为(在编译时)任何可变参数类型都可以作为可变参数集的一部分被接受。

As the other answers have shown, "%s" is a format specifier that expects a NULL terminated character string. 如其他答案所示, "%s"是一种格式说明符,期望以NULL结尾的字符串。 Passing a std::string in this case, is likely undefined. 在这种情况下,传递std :: string可能是不确定的。

If it works in DEBUG mode, it is likely just "lucky" in that the implementation happens to print the correct result (likely stemming from a c-style cast of the std::string object to a character pointer). 如果它在DEBUG模式下工作,则很可能是“幸运的”,因为该实现恰好会打印正确的结果(可能源于std :: string对象的c样式强制转换为字符指针)。

That shouldn't work. 那不行 Its likely that you are hitting undefined behavior. 很可能是您遇到未定义的行为。

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

You should actually probably be using streams instead. 实际上,您实际上应该使用流。

That is wrong. 那是错的。 You should be writing this: 您应该这样写:

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

An object of type std::string cannot be passed to sprintf as there is no format specifier corresponds to std::string . 无法将类型为std::string的对象传递给sprintf因为没有格式说明符对应于std::string Also, %s expects object of type char* or char[] , and c_str() function returns char* , so the above would work. 此外, %s期望使用char*char[]类型的对象,并且c_str()函数返回char* ,因此上述方法可以正常工作。

If you are going to mix up c and c++ then (for performance reasons, based on the comment you gave) then its a good idea to wrap the functions in c++ to avoid these subtle bugs. 如果要混合使用c和c ++,则(出于性能原因,基于您的评论),将函数包装在c ++中以避免这些细微的错误是个好主意。

struct console_out
{
  static void 
  print(const string& s)
  {
    sprintf(buf, "%s", s.c_str());
  }
  //other overloads should you want them
}

Be careful once and let the compiler be careful thereafter. 请小心一次,然后让编译器小心。

I sometimes think bugs like this are too easy in c and c++, but we can muddle through. 有时我认为这样的错误在c和c ++中太容易了,但是我们可以解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM