Changing a string literal, or, when is "" not really ""? 
Author Message
 Changing a string literal, or, when is "" not really ""?

Okay, I understand that if you have something like

    char *str = "This is a string";

that _str_ may not be (and if I remember correctly, the standard says
*should* not be) writable, meaning I couldn't change "This is a string"
to "This is not a string".  

However, I discovered a {*filter*} little bug in my code the other day where I
was changing the contents of a string literal by passing it to a
function.  

The function is supposed to return two pathnames, one pathname pointing
to a set of files waiting to be processed, and the other pointing to
where those files should be placed after processing.  The basic structure
is

    void SetupQueues (char *waitQueue, char *doneQueue, int *isOk);

Through some act of unknown and unknowable stupidity, I was passing the
string literal "" as the doneQueue parameter, as follows:

    SetupQueues (jQueue, "", &isOk); /* "" should really be dQueue */

After this call, "" has been changed to whatever the doneQueue parameter
returns.  Later on, I call a function which trys to walk down the
directory structure starting at the waitQueue path, as follows:

    void ListFiles (char *path, char *file, int *isOk);

This function concatenates _file_ to _path_ and checks for the existence
of that file.  If the file exists and is a regular file, the function
places it's name in a special queue for processing.  If the file exists
and is a directory, then ListFiles scans that entire directory.  Now, the
first time I call it, I want it to start at the path returned in jQueue,
so I call it as

    ListFiles (jQueue, "", &isOk);

However, "" has been modified by the call to SetupQueues, so ListFiles
starts at jQueue+whatever the destination queue name is, which doesn't
exist, so the program says "nope, no files there" and stares at me like
some dumb animal waiting to be fed.

Now, does anyone know what the standard has to say about this?  It was my
understanding that the global string space should not be writeable, but
obviously it is, at least on a Power Mac using MPW ETO #18.  Has anyone
else run into this?  Can anyone else duplicate this?  Is this just
further proof that I should not be programming for a living?

John F. Bode



Wed, 30 Dec 1998 03:00:00 GMT  
 Changing a string literal, or, when is "" not really ""?



Quote:
>Now, does anyone know what the standard has to say about this?

The behaviour of writing to a string literal (not to mention accessing
outsde the bounds of an array which, after all is what a string literal
is) is undefined. That means that *anything* your compiler does is correct.

Quote:
> It was my
>understanding that the global string space should not be writeable, but
>obviously it is, at least on a Power Mac using MPW ETO #18.

The standard doesn't say it can't be writable. What this compiler
does is just one valid implementation of undefined behaviour.

Of course since you have no guarantee as to what such operations will
do it is pointless as well as dangerous to include them in your code.

--
-----------------------------------------


-----------------------------------------



Wed, 30 Dec 1998 03:00:00 GMT  
 Changing a string literal, or, when is "" not really ""?


Quote:
> Okay, I understand that if you have something like

>     char *str = "This is a string";

> that _str_ may not be (and if I remember correctly, the standard says
> *should* not be) writable, meaning I couldn't change "This is a string"
> to "This is not a string".  

> However, I discovered a {*filter*} little bug in my code the other day where I
> was changing the contents of a string literal by passing it to a
> function.  

> The function is supposed to return two pathnames, one pathname pointing
> to a set of files waiting to be processed, and the other pointing to
> where those files should be placed after processing.  The basic structure
> is

>     void SetupQueues (char *waitQueue, char *doneQueue, int *isOk);

> Through some act of unknown and unknowable stupidity, I was passing the
> string literal "" as the doneQueue parameter, as follows:

>     SetupQueues (jQueue, "", &isOk); /* "" should really be dQueue */

> After this call, "" has been changed to whatever the doneQueue parameter
> returns.  Later on, I call a function which trys to walk down the
> directory structure starting at the waitQueue path, as follows:

>     void ListFiles (char *path, char *file, int *isOk);

> This function concatenates _file_ to _path_ and checks for the existence
> of that file.  If the file exists and is a regular file, the function
> places it's name in a special queue for processing.  If the file exists
> and is a directory, then ListFiles scans that entire directory.  Now, the
> first time I call it, I want it to start at the path returned in jQueue,
> so I call it as

>     ListFiles (jQueue, "", &isOk);

> However, "" has been modified by the call to SetupQueues, so ListFiles
> starts at jQueue+whatever the destination queue name is, which doesn't
> exist, so the program says "nope, no files there" and stares at me like
> some dumb animal waiting to be fed.

> Now, does anyone know what the standard has to say about this?  It was my
> understanding that the global string space should not be writeable, but
> obviously it is, at least on a Power Mac using MPW ETO #18.  Has anyone
> else run into this?  Can anyone else duplicate this?  Is this just
> further proof that I should not be programming for a living?

Changing a string literal results in undefined behavior.  Anything
might happen and the implmentation is not required to issue a
diagnostic or document what happens.  String literals need not be put
in write protected memory.

Realistically, you're almost certain to get one of two results if you
simply replace characters in a string literal.  Either the literal
will be changed (possibly including other instances of the same
literal string in  your program) or you will get some kind of memory
exception.

If you increase the length, things may get worse since you might
overwrite memory used by something else.

Michael M Rubenstein



Wed, 30 Dec 1998 03:00:00 GMT  
 Changing a string literal, or, when is "" not really ""?


Quote:
>Okay, I understand that if you have something like
>    char *str = "This is a string";
>that _str_ may not be (and if I remember correctly, the standard says
>*should* not be) writable, meaning I couldn't change "This is a string"
>to "This is not a string".  
>However, I discovered a {*filter*} little bug in my code the other day where I
>was changing the contents of a string literal by passing it to a
>function.  

I think they were telling me it is implementation-dependent... the standard
says it can be placed in read-only memory but doesn't have to be.  borland
compilers put it in read/write memory; the compiler I am writing puts it
in read-only memory and writing could cause a code crash.

Quote:
>The function is supposed to return two pathnames, one pathname pointing
>to a set of files waiting to be processed, and the other pointing to
>where those files should be placed after processing.  The basic structure
>is
>    void SetupQueues (char *waitQueue, char *doneQueue, int *isOk);
>Through some act of unknown and unknowable stupidity, I was passing the
>string literal "" as the doneQueue parameter, as follows:
>    SetupQueues (jQueue, "", &isOk); /* "" should really be dQueue */
>After this call, "" has been changed to whatever the doneQueue parameter
>returns.  Later on, I call a function which trys to walk down the
>directory structure starting at the waitQueue path, as follows:
>    void ListFiles (char *path, char *file, int *isOk);
>This function concatenates _file_ to _path_ and checks for the existence
>of that file.  If the file exists and is a regular file, the function
>places it's name in a special queue for processing.  If the file exists
>and is a directory, then ListFiles scans that entire directory.  Now, the
>first time I call it, I want it to start at the path returned in jQueue,
>so I call it as
>    ListFiles (jQueue, "", &isOk);
>However, "" has been modified by the call to SetupQueues, so ListFiles
>starts at jQueue+whatever the destination queue name is, which doesn't
>exist, so the program says "nope, no files there" and stares at me like
>some dumb animal waiting to be fed.

Another potential problem is if you put the address of this into a list,
you will be using the same address every time you put that string in a list.

Quote:
>Now, does anyone know what the standard has to say about this?  It was my
>understanding that the global string space should not be writeable, but
>obviously it is, at least on a Power Mac using MPW ETO #18.  Has anyone
>else run into this?  Can anyone else duplicate this?  Is this just
>further proof that I should not be programming for a living?

Like I say, borland compilers do this too.  I can't remember what GCC does
though...

David

- Show quoted text -

Quote:
>John F. Bode



Wed, 30 Dec 1998 03:00:00 GMT  
 Changing a string literal, or, when is "" not really ""?

What it comes down to is that, although literals ought not to be writable, the
original design of the C language allowed them to be, and some blithering
idiots actually made their code depend on it, and they raise holy hell
whenever their compiler vendor tries to change it.  Therefore, it is still
allowed, even though it's an incredibly stupid trick to pull.

For example, they'll do something like have in the beginning of their
program:

   puts ("Enter report header"); gets ("This is the page header");

and then, later:

   fputs ("This is the page header", report); fputc ('\n', report);

A good compiler will usually have a pragma or compiler option to enforce
sensible behavior, which not only removes a source of bugs, but, in some
environments, will also improve performance by moving all string literals to
read-only pages that do not need to be swapped out and can be shared among
multiple processes.



Fri, 01 Jan 1999 03:00:00 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. Setting not Null field to ""(empty string) does not work with CRecordset

2. Setting not Null field to ""(empty string) does not work with CRecordset

3. remove() vrs fopen("""w")

4. Displaying binary data as ascii "1"'s and "0"'s

5. Looking for "Shroud"/"Obfus"

6. ""help with TSR""

7. Parse trees and "("")"

8. Error "free"-ing "malloc"-ed memory

9. Displaying binary data as ascii "1"'s and "0"'s

10. why not "cout", "<<" , and "endl"??

11. Release Compile strange "null" literal

12. Not "string-oriented" async server

 

 
Powered by phpBB® Forum Software