Changing a string literal, or, when is "" not really ""?
Author |
Message |
John F. Bod #1 / 5
|
 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 |
|
 |
Lawrence Kirb #2 / 5
|
 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 |
|
 |
Mike Rubenste #3 / 5
|
 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 |
|
 |
George C. Lindau #4 / 5
|
 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 Quote: >John F. Bode
|
Wed, 30 Dec 1998 03:00:00 GMT |
|
 |
kenne.. #5 / 5
|
 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 |
|
|
|