Bul*_*aza 1 c++ append undefined-behavior visual-studio visual-c++
在我的代码中,我使用日志语句以便更好地了解发生了什么。有时我会编写如下代码:
int i = 1337;
// More stuff...
logger->info("i has the following value: " + i);
Run Code Online (Sandbox Code Playgroud)
当在调试模式下编译和执行时,它不会i按预期打印出来(例如,这就是它在 Java/C# 中的工作方式),而是打印一些乱码。然而,在发布模式下,这可能会导致整个应用程序崩溃。C++标准对于将整数附加到std::string我在这里所做的事情有什么规定?
当我编译调用像这样的明显未定义行为的代码时,为什么编译器根本不警告我?我错过了什么吗?我正在使用 Visual Studio 2022 (MSVC)。执行日志记录语句的正确方法是将 intstd::string显式转换为 a:
logger->info("i has the following value: " + std::to_string(i));
Run Code Online (Sandbox Code Playgroud)
然而,这个错误在开发过程中很容易被忽视。我的警告级别设置为Level4 (/W4)。
Gos*_*low 11
问题是在
\nlogger->info("i has the following value: " + i);\nRun Code Online (Sandbox Code Playgroud)\n您没有与 一起工作std::string。您正在将 an 添加int到字符串文字,即const char[]数组。在某些情况下,该const char[]值会衰减为const char*指针。在这种情况下,int指针向前前进 1337 个字符,这远远超出了字符串文字的末尾,因此是未定义的行为。
您应该获得一个更好的编译器来警告您这一点,即:
\nfoo.cc:7:42: warning: offset \xe2\x80\x981337\xe2\x80\x99 outside bounds of constant string [-Warray-bounds]\n 7 | foo("i has the following value: " + i);\n | ^\nRun Code Online (Sandbox Code Playgroud)\n您可以使用std::string如下文字:
#include <string>\nusing namespace std::literals;\n\nvoid foo(std::string);\n\nvoid bla() {\n int i = 1337;\n foo("i has the following value: "s + i);\n}\nRun Code Online (Sandbox Code Playgroud)\n然后你会得到一个“更好”的错误,即“std::string + int”不是 C++ 中的东西:
\nfoo.cc:8:40: error: no match for \xe2\x80\x98operator+\xe2\x80\x99 (operand types are \xe2\x80\x98std::__cxx11::basic_string<char>\xe2\x80\x99 and \xe2\x80\x98int\xe2\x80\x99)\n 8 | foo("i has the following value: "s + i);\n | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~\n | | |\n | std::__cxx11::basic_string<char> int\n...\ngoing on for 147 lines\nRun Code Online (Sandbox Code Playgroud)\n在此之后,很明显您想要的是:
\nlogger->info("i has the following value: "s + std::to_string(i));\nRun Code Online (Sandbox Code Playgroud)\n使用std::string文字可以避免这样的错误,因为它将警告(编译器甚至不会给出)变成硬错误,迫使您编写正确的代码。所以我建议使用s对所有字符串使用后缀。
这条线是正确的,
logger->info("i has the following value: " + i);
Run Code Online (Sandbox Code Playgroud)
在表达式中
"i has the following value: " + i
Run Code Online (Sandbox Code Playgroud)
这里使用了指针运算。
例如,如果你会写
logger->info("i has the following value: " + 6);
Run Code Online (Sandbox Code Playgroud)
那么如果写这一行有相同的效果
logger->info("the following value: ");
Run Code Online (Sandbox Code Playgroud)
就是这一行
logger->info("i has the following value: " + i);
Run Code Online (Sandbox Code Playgroud)
相当于线
logger->info( &"i has the following value: "[i]);
Run Code Online (Sandbox Code Playgroud)
C++ 标准对于将 int 附加到 std::string 有何规定,就像我在这里所做的那样
表达式中没有 类型的对象std::string。使用的字符串文字只有一个普通的数组类型,它是带有指针算术的表达式的操作数。在表达式中,字符串文字隐式转换为指向其类型的第一个元素的指针const char *。