Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a modifiable string literal in C++

Tags:

c++

string

Is it possible to create a modifiable string literal in C++? For example:

char* foo[] = {
    "foo",
    "foo"
};
char* afoo = foo[0];
afoo[2] = 'g'; // access violation

This produces an access violation because the "foo"s are allocated in read only memory (.rdata section I believe). Is there any way to force the "foo"s into writable memory (.data section)? Even via a pragma would be acceptable! (Visual Studio compiler)

I know I can do strdup and a number of other things to get around the problem, but I want to know specifically if I can do as I have asked. :)

like image 631
Anne Avatar asked Jun 16 '10 16:06

Anne


2 Answers

Since this is C++, the "best" answer would be to use a string class (std::string, QString, CString, etc. depending on your environment).

To answer your question directly, you're not supposed to modify string literals. The standard says this is undefined behavior. You really do need to duplicate the string one way or another, otherwise you're writing incorrect C++.

like image 151
Cogwheel Avatar answered Oct 07 '22 12:10

Cogwheel


I think the closest you can come is to initialize a plain char[] (not a char*[]) with a literal:

char foo[] = "foo";

That'll still perform a copy at some point though.

The only other way around that would be to use system level calls to mark the page that a string literal resides in as writeable. At that point you're not really talking about C or C++, you're really talking about Windows (or whatever system you're running on). It's probably possible on most systems (unless the data is really in ROM, which might be the case on an embedded system for example), but I sure don't know the details.

Oh, and don't forget that in your example:

char* foo[] = {
    "foo",
    "foo"
};

Since the standard (C99 6.4.5/6 "String literals") says:

It is unspecified whether these arrays are distinct provided their elements have the appropriate values.

There's no certainty about whether the 2 pointers in that array will point to the same or separate objects. Nearly all compilers will have those pointers point to the same object at the same address, but they don't have to and some more complicated situations of pointers to string literals might have the compiler coming up with 2 separate identical strings.

You could even have a scenario where one string literal exists 'inside' another:

char* p1 = "some string";
char* p2 = "string";

p2 may well be pointing at the tail end of the string pointed to by p1.

So if you start changing string literals by some hack you can perform on a system, you may end up modifying some 'other' strings unintentionally. That's one of the things that undefined behavior can bring along.

like image 22
Michael Burr Avatar answered Oct 07 '22 13:10

Michael Burr