In my code I use logging statements in order to better see what’s going on. Sometimes I write code like the following:
int i = 1337;
// More stuff...
logger->info("i has the following value: " + i);
When compiled and executed in debug mode this does not print out i as expected (this is how it would work in Java/C# for example), it rather prints something garbled. In release mode however this might as well crash the entire application. What does the C++ standard say about appending ints to a std::string like I’m doing here?
Why does the compiler not warn me at all when I compile code invoking obvious undefined behavior like this? Am I missing something? I’m using Visual Studio 2022 (MSVC). The correct way to do the logging statement would be converting the int to a std::string explicitly:
logger->info("i has the following value: " + std::to_string(i));
However this bug easily slips through during development. My warning level is set to Level4 (/W4).
>Solution :
The problem is that in
logger->info("i has the following value: " + i);
you are not working with std::string. You are adding a string literal, i.e. a const char *, and an int. What this does it advance the pointer by 1337, which is way beyond the end of the string literal and therefore undefined behavior.
You should get a better compiler:
foo.cc:7:42: warning: offset ‘1337’ outside bounds of constant string [-Warray-bounds]
7 | foo("i has the following value: " + i);
| ^
You can use a std::string literal like this:
#include <string>
using namespace std::literals;
void foo(std::string);
void bla() {
int i = 1337;
foo("i has the following value: "s + i);
}
and then you get a "nice" error that "std::string + int" isn’t a thing in c++:
foo.cc:8:40: error: no match for ‘operator+’ (operand types are ‘std::__cxx11::basic_string<char>’ and ‘int’)
8 | foo("i has the following value: "s + i);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~
| | |
| std::__cxx11::basic_string<char> int
...
going on for 147 lines
After this it should be obvious that what you want is:
logger->info("i has the following value: "s + std::to_string(i));
Using std::string literals avoids mistakes like this because it turns warnings (which your compiler doesn’t even give) into hard errors forcing you to write correct code. So I recommend using the s suffix for all strings.