Complication overload

Every kid knows that string processing in C is mundane job and it pretty easy to make a mistake. That’s why in C++ we have std::string class, right? Now we can easily concatenate strings, do other stuff, concatenate strings… Concatenate strings. Let’s do some concatenation.

#include <string>
#include <cstdio>
int main(int argc, char** argv)
{
 std::string text = "current app is: \"";
 text = text + argv[0] + '"';
 puts(text.c_str());
 return 0;
}

Output

current app is: "./prog"

So far everything is ok, but there is small inefficiency – instead text=text+… we can replace it with construction text+=… This will save additional reallocation. Besides, concatenation with std::string is easy – what can possibly go wrong?

#include <string>
#include <cstdio>
int main(int argc, char** argv)
{
 std::string text = "current app is: \"";
 //text = text + argv[0] + '"';
 text += argv[0] + '"';
 puts(text.c_str());
 return 0;
}

Output

current app is: "r/local/bin:/usr/bin:/bin

What just happened? My application for sure does not have this fancy name…
Let’s take a closer look at line:

text += argv[0] + '"';

It looks quite intuitively and harmless, and it should be the same as text=text+argv[0]+'”‘, which worked in previous case. Well, it actually causes a problem.

Expression ‘”‘ is treated as integer with value 0x22 (ascii code of ). At first right side is executed so we will get expression  argv[0]+'”‘ which is substitute for argv[0]+0x22. This expression will be finally concatenated to text. Due to pointer arithmetic argv[0]+0x22 is just a pointer that points outside the argv[0] so we will reference some random memory.
Expression text=text+argv[0]+'”‘ is different because at first text+argv[0] is executed which results in std::string. Then operator+(‘”‘) is executed on string which give us correct result.

As you can see expressions a=a+b and a+=b will not necessary give always same results, not only because of performance.