Topic: initialized 'global' (extern) char arrays
Author: mbb@litwin.com (Mark Beyleveld)
Date: Fri, 8 Jan 1993 13:55:47 GMT Raw View
jimlynch@netcom.com (Jim Lynch) writes:
>I am given to understand that the storage allocated by
>
>char *x = "abcde" ;
>
>is not writable.
As was also pointed out, the problem is more subtle, in that somewhere
further into the program, one cannot distinguish between the above, and
strings that were malloc'ed.
There are two solutions, depending on what the author intended:
1) If it is supposed to be read-only, declare it as
const char * const x = "abcde" ;
Note that this asserts that the value of the pointer may change, but what
is pointed to is constant.
Also, note that unless the constness is deliberately cast away, one
should not be able to attempt to change the data.
2) If it is not to be read-only,
char * x = strdup("abdce");
This is ugly, in that twice the storage is required, but now it is legal
to say free(x);
There is a similar but more subtle problem:
char * x = strdup("abcde");
char * y = new char[6];
(void) strcpy(y, "abcde");
Further down the road, I want to dispose of the data (which is legal,
since both are dynamically allocated). Do I use free or delete? If
new and delete have not been overloaded, most heap manager implementations
would not care, but this is relying on compiler implementation.
One could declare internal coding standards, but if one uses a third-party
library (for which there may be only object code), what then?
--
---------------------------------------------------------------------
Mark Beyleveld
Litwin Process Automation
Author: steve@taumet.com (Steve Clamage)
Date: Sat, 9 Jan 1993 17:22:28 GMT Raw View
mbb@litwin.com (Mark Beyleveld) writes:
>char * x = strdup("abcde");
>char * y = new char[6];
>(void) strcpy(y, "abcde");
>Further down the road, I want to dispose of the data (which is legal,
>since both are dynamically allocated). Do I use free or delete?
Is it not a good idea to use a C library version of strdup (which is
not part of the C Standard anyway) in a C++ program, for exactly this
reason. If you need strdup, you would be better off writing your own
as a C++ function, possibly giving it another name to reduce confusion
for the readers of the program.
--
Steve Clamage, TauMetric Corp, steve@taumet.com
Author: jimlynch@netcom.com (Jim Lynch)
Date: Thu, 7 Jan 1993 03:24:58 GMT Raw View
I am given to understand that the storage allocated by
char *x = "abcde" ;
is not writable. In terms of whatever standard exists, is it exactly the same as
const char *x = "abcde" ; // ?
The reason I ask is that I used such a construct in gcc-2.3.2 (yes, I plan to
upgrade) as follows:
char *x = "some string" ;
main()
{
something(x[0]) ;
}
where the prototype for something looks like
void something(char &z) ;
and modifies that which is referred to by z.
So when something() got around to modifying, the system dumped core, claiming
a segmentation fault. Shouldn't the compiler have warned me?
Also, some internal issues:
Assuming that x is a const char *, does the C compiler see the argument to
something() in main() as needing a type conversion from const char to plain
ol' char? If so, shouldn't the compiler warn about this (possibly probematic)
kind of conversion?
Someone told me that even though the ANSI standard says that x is unwritable,
the compiler won't implement this by making it a const. My feeling is that this
is a mistake: unwritable should imply const (although my assumption was the
other way around: unwritable is implemented through using const.)
-Jim
Author: steve@taumet.com (Steve Clamage)
Date: Thu, 7 Jan 1993 17:44:01 GMT Raw View
jimlynch@netcom.com (Jim Lynch) writes:
>I am given to understand that the storage allocated by
>char *x = "abcde" ;
>is not writable. In terms of whatever standard exists, is it exactly the same as
>const char *x = "abcde" ; // ?
It is not exactly the same. Whether literal strings are writeable is
up to the implementation, not mandated by the Standard. The sequence
char *p = "abcde";
*p = 'z';
is allowed to succeed or fail. The compiler is not obligated to warn you
that you are writing to readonly storage if that is the case. For one
thing, it can't always tell. Consider
void foo(char *q) { *q = 'z'; }
This function could be called from another translation unit. It is
legal to pass such a function a pointer to a literal string, and the
function doesn't know what is being passed to it. It could fail only
at run time, absent cross-module type checking.
The sequence
const char *p = "abcde";
*p = 'z';
must be diagnosed as an error. Type "const char*" is not the same
type as "char *".
Three rules for happy living:
1. Don't assume you can write to literal strings.
2. Don't assign or pass a literal string to a char*.
3. Declare a parameter to be const char* if the string is only read.
(Hmmm. Maybe this is too narrow a view of happy living...)
--
Steve Clamage, TauMetric Corp, steve@taumet.com
Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Fri, 8 Jan 1993 01:23:49 GMT Raw View
jimlynch@netcom.com (Jim Lynch) writes:
>I am given to understand that the storage allocated by
>
>char *x = "abcde" ;
>
>is not writable.
Correct.
>The reason I ask is that I used such a construct in gcc-2.3.2 ...
[example omitted]
>... Shouldn't the compiler have warned me?
With gcc, use the -Wwrite-strings option. Here's an extract from the
manual:
-Wwrite-strings
Give string constants the type const char[length] so
that copying the address of one into a non-const char *
pointer will get a warning. These warnings will help
you find at compile time code that can try to write
into a string constant, but only if you have been very
careful about using const in declarations and proto-
types. Otherwise, it will just be a nuisance; this is
why we did not make `-Wall' request these warnings.
--
Fergus Henderson fjh@munta.cs.mu.OZ.AU
This .signature virus is a self-referential statement that is true - but
you will only be able to consistently believe it if you copy it to your own
.signature file!