When It Rains

One of the finest engineers I know, Bruce Dawson, pointed out a fatal flaw in my GDC 2008 string code. Even more devastating, it’s not a subtle flaw. This one was staring me right in the face and I didn’t even see it. Recall the code:
char* s = "abcdef";
char u[] = "def";
u[0] = ‘x’; // danger, NOT!
According to the C++ Standard, string literals can overlap in memory, so the "def" string could overlap with the "abcdef" portion. That much is still true. However, the "u" string is a copy of "def", not a pointer into it. When you declare a string with angle brackets, you have a character array, not a string pointer. You can modify the "u" string to your heart’s content and it will never ever modify "s". That’s because "u" is a character array, not a pointer.
Here’s a revision:
char* sz = "abcdef";
char* uz = "def";
char vz[] = "ef";
assert( (uz < sz) && (uz > sz+6) ); // invalid assumption

sz[n] = ‘x’; // undefined behavior
uz[n] = ‘x’; // undefined behavior

vz]n] = ‘x’; // perfectly reasonable, as long as n < 2

Now we have two string pointers that point at literals. The "def" portion could overlap with the end of the "abcdef" portion in memory, so it’s not safe to assume that the pointer uz does not point somewhere within the sz range. Modifying the literal is still not allowed, even though we’ve declared non-const pointers (2.13.4/2 says "the effect of attempting to modify a string literal is undefined"). Finally, the character array vz contains a copy of "ef" and we can modify vz safely.
As I said when I was giving the talk, C++ is a complicated language. It’s up to all of to continue educating each other about the nuances. Sometimes explaining your bonehead mistakes is the best way to continue the education process. Embarrassed

Leave a Reply


WordPress.com Logo


Google photo


Twitter picture


Facebook photo


Connecting to %s