I recently stumbled upon a subtle bug in a benchmark code which again reminds me to never use C++ again, if I can.
Here’s a buggy snippet from this code (simplified):
// BUGGY ostringstream os; int i = 1; os << "foo-" << i << ".dat"; const char *filename = os.str().c_str(); int fd = open(filename, O_RDONLY);
You may expect above code to try open a file named
foo-1.dat but that’s not what is happening here.
In this snippet,
os.str() create a temporary
string object which is destroyed immediately after call to
c_str() method. So,
filename ends up pointing to freed memory which can of course contain arbitrary content (till you reach a
This fix would be to first assign result of
os.str() to a string object explicitly which would have lifetime of the current scope:
// FIXED ostringstream os; int i = 1; os << "foo-" << i << ".dat"; string s = os.str(); const char *filename = s.c_str(); int fd = open(filename, O_RDONLY);
Such bugs would be much harder to catch and fix in larger programs with complicated abstractions, typical of C++ programs.
Fortunately, we now have alternative languages like Rust which can detect such errors at compile time while giving a level of control and performance equivalent to C/C++.