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
 
Advertisements
This entry was posted in C++. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s