Anne
Anne

Reputation: 53

Create a modifiable string literal in C++

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. :)

Upvotes: 5

Views: 3462

Answers (6)

Michael Burr
Michael Burr

Reputation: 340168

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.

Upvotes: 5

John
John

Reputation: 1

Yes.

   (char[]){"foo"}

Upvotes: -3

Ferdinand Beyer
Ferdinand Beyer

Reputation: 67137

You could create a multidimensional array of chars:

#include <iostream>

int main(int argc, char** argv)
{
    char foo[][4] = {
        "foo",
        "bar"
    };
    char* afoo = foo[0];
    afoo[2] = 'g';
    std::cout << afoo << std::endl;
}

More verbose way to define the array:

char foo[][4] = {
    {'f', 'o', 'o', '\0'},
    {'b', 'a', 'r', '\0'}
};

Upvotes: 1

zerm
zerm

Reputation: 2842

I would not do this. Therefore, I can only provide a nasty ugly hack you could try out: Get the page where your constant literal resides and unprotect that page. See VirtualProtect() function for Win32. However, even if this works, it will not guarantee the correct behavior all the time. Better don't do it.

Upvotes: 1

Edward Strange
Edward Strange

Reputation: 40849

If you store your string in an array you can change it.

There's no way to 'correctly' write to read-only memory.

You could, of course, stop using C-strings.

Upvotes: 2

Cogwheel
Cogwheel

Reputation: 23217

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++.

Upvotes: 9

Related Questions