08 Jul, 2007, Guest wrote in the 1st comment:
Votes: 0
So it seems our buddies over at GNU are having some fun at our expenses once again. Along with several other projects, including such high profile ones as KDE. The problem? It seems that they decided to include the following fun bit of crap in the -Wall option:
Quote
`-Wwrite-strings'
When compiling C, 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; when compiling
C++, warn about the deprecated conversion from string constants to
`char *'. 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
prototypes. Otherwise, it will just be a nuisance; this is why we
did not make `-Wall' request these warnings.


The -Wwrite-strings warning flag is an optional extra flag in GCC <= 4.1x but not in GCC >= 4.2. If you don't have Gc 4.2, you can get a face full of the following just for the fun of it. I did this on SmaugFUSS, choose your own favorite codebase to have fun with.
Quote
act_comm.c: At global scope:
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''
act_comm.c:2784: warning: deprecated conversion from string constant to 'char*''


I have been unable to find a means of getting the compiler to turn this off with a "stop spamming me" style option. So it would appear that upgrading to GCC 4.2 is going to give everyone here an assload of grief. For what appears to be very little gain.

So why is this such a problem? Isn't this supposed to be good? You might think so until you realize that every codebase that has a command format like this:
void do_something( CHAR_DATA *ch, char *argument )

is going to complain bitterly that argument isn't a const. Yes. I can see the light bulbs coming on now. What of commands that break that up with one_argument? What about commands that trigger a help response by calling do_something( ch, "" );

They'll generate the same crapload of warnings as above.

Ordinarily I'm all in favor of GNU tightening things up and producing warnings and errors on legitimate problems, but I think springing this on people without mentioning it in the release notes is just wrong. A quick Googling reveals the specific error only has a couple hundred hits, but some of them were generated on large high profile projects like KDE. Now presumably KDE is run by professional coders. Usually well above the caliber you find on the average MUD. If *THEY* have thousands of lines of code with this problem, is it entirely unreasonable that our hobby projects might have the same problems? How long do you think the KDE guys are gonna need to clean up that gigantic mess? How long is it going to take MUD coders to clean up this mess? What about all those old dinosaur codebases that nobody has updated in 15 years? This is only going to add more crap to sift through to look for legitimate errors.
08 Jul, 2007, Conner wrote in the 2nd comment:
Votes: 0
*sigh* Lovely.. thanks for the warning, at least. :sad:
08 Jul, 2007, Scandum wrote in the 3rd comment:
Votes: 0
Easy to fix.

tt++ -e "#gag deprecated conversion;#con packet 1000;#run ttmake make"
08 Jul, 2007, Brinson wrote in the 4th comment:
Votes: 0
*hates the people at Gnu even more than when they moved to 3 to 4*
20 Aug, 2007, Vorlin wrote in the 5th comment:
Votes: 0
Yeah, I've always hated the whole "deprecated errors" listing myself…since it doesn't really break anything and just reports, I'd redirect error output to /dev/null (assuming that's the only error I was getting, rofl) and keep going until I decided to figure out what to do. Either that or to a file and look at it to make sure I wasn't missing something really important but generally, nothing will compile if X number of errors are made or something really is wrong.
20 Aug, 2007, Guest wrote in the 6th comment:
Votes: 0
Well what's worse is that if you're using gcc 4.2 either by choice or because your environment came with it, you've got almost no recourse other than to turn off -Wall. But doing so with a lot of mud codebases will block out many of the warnings that let us know we wrote rubbish and tried to pass it off as code.

The whole DO_FUN format most of us are used to is going to create a real problem. I haven't worked out a good way around it in my head yet. And since dirty compiles bother me to no end I'm sure I'll eventually spend a great deal of time fiddling with it. But that's time I could be using for far more interesting things.
20 Aug, 2007, Dorian wrote in the 7th comment:
Votes: 0
Samson said:
I have been unable to find a means of getting the compiler to turn this off with a "stop spamming me" style option. So it would appear that upgrading to GCC 4.2 is going to give everyone here an assload of grief. For what appears to be very little gain.


Why little gain? This defect in C (and inherited by C++) has been a thorn in the language's side for years. Moreover, it has been said for years that programmers should treat string literals as const arrays. It was bound to happen sometime that compilers got fussy about it.

Quote
So why is this such a problem? Isn't this supposed to be good? You might think so until you realize that every codebase that has a command format like this:
void do_something( CHAR_DATA *ch, char *argument )

is going to complain bitterly that argument isn't a const. Yes. I can see the light bulbs coming on now. What of commands that break that up with one_argument? What about commands that trigger a help response by calling do_something( ch, "" );

They'll generate the same crapload of warnings as above.


Then update the code for const-correctness. Yes, it'll be a pain, but it'll be better in the long run. AFAICR, none of the Merc code attempts to write to the argument parameter, so it shouldn't be that difficult. I _think_ you might be able to get away with something like sed -e 's/char *argument/const char *argument/;' inputfile. However, don't quote me on that.

Quote
Ordinarily I'm all in favor of GNU tightening things up and producing warnings and errors on legitimate problems, but I think springing this on people without mentioning it in the release notes is just wrong. A quick Googling reveals the specific error only has a couple hundred hits, but some of them were generated on large high profile projects like KDE. Now presumably KDE is run by professional coders. Usually well above the caliber you find on the average MUD. If *THEY* have thousands of lines of code with this problem, is it entirely unreasonable that our hobby projects might have the same problems? How long do you think the KDE guys are gonna need to clean up that gigantic mess? How long is it going to take MUD coders to clean up this mess? What about all those old dinosaur codebases that nobody has updated in 15 years? This is only going to add more crap to sift through to look for legitimate errors.


Oh goodness… Shame on KDE and those of old, then. This string literal issue has been a known problem since 1989 when ANSI allowed string literals to be placed in a char pointer but allowed the implementation to put them in non-modifiable memory. If KDE uses this conversion, then shame on them. It's their own fault for not having enough foresight and planning to avoid this issue.
20 Aug, 2007, kiasyn wrote in the 8th comment:
Votes: 0
Dorian said:
Then update the code for const-correctness. Yes, it'll be a pain, but it'll be better in the long run. AFAICR, none of the Merc code attempts to write to the argument parameter, so it shouldn't be that difficult. I _think_ you might be able to get away with something like sed -e 's/char *argument/const char *argument/;' inputfile. However, don't quote me on that.


one_argument does.
20 Aug, 2007, Dorian wrote in the 9th comment:
Votes: 0
kiasyn said:
Dorian said:
Then update the code for const-correctness. Yes, it'll be a pain, but it'll be better in the long run. AFAICR, none of the Merc code attempts to write to the argument parameter, so it shouldn't be that difficult. I _think_ you might be able to get away with something like sed -e 's/char *argument/const char *argument/;' inputfile. However, don't quote me on that.


one_argument does.


Where? I'm looking at one_argument in SMAUG FUSS 1.7. I don't see any place where one_argument writes to the string. All I see is it advancing the pointer, which adding the const would have no effect on the operation of the code. AFAICS, the codebases could be updated without any major re-editing, but it would be a pain to make a bunch of small changes.
21 Aug, 2007, Guest wrote in the 10th comment:
Votes: 0
Well if the codebase can be updated and not bother one_argument, it won't be quite so bad. But…..

argument = one_argument( argument, arg );

clearly DOES try to write to the string. If it's a const then won't the compiler come down on you for trying to write to read-only strings?
21 Aug, 2007, Guest wrote in the 11th comment:
Votes: 0
So. I added the warning flag -Wwrite-strings. I got back the expected sea of "errors". The very first ones I run into are ones I have no direct control over.

putenv( "TERM=vt100" );
putenv( "COLUMNS=80" );
putenv( "LINES=24" );


shell.cpp:132: warning: deprecated conversion from string constant to 'char*''
shell.cpp:133: warning: deprecated conversion from string constant to 'char*''
shell.cpp:134: warning: deprecated conversion from string constant to 'char*''

So. If this is such a scary problem is there a reason even the C/C++ libraries contain these ghastly mistakes? :)
21 Aug, 2007, Mister wrote in the 12th comment:
Votes: 0
You can always compile with -Wall -Wno-write-strings. Also, this change is good, as it will find some difficult-to-locate bugs. I remember a bug in some mindcloud version, where 'argument' in do_say gets modified when the speaker is drunk. Then, of course, a do_say(ch,"hi") had nefarious consequences. Since many functions won't modify its arguments, why not make them const in the first place?

Yes, fixing the code to achieve const-correctness is a chore, although not difficult, and certainly possible, I've done it.

And Samson, "argument = one_argument( argument, arg );" does NOT modify the string. it modifies the pointer.

But I agree on that putenv stuff, although system headers shouldn't be changed… Anyway, you can 'fix' it with:

static char *var = "TERM=vt100";
putenv(var);
21 Aug, 2007, Conner wrote in the 13th comment:
Votes: 0
mister said:
But I agree on that putenv stuff, although system headers shouldn't be changed… Anyway, you can 'fix' it with:

static char *var = "TERM=vt100";
putenv(var);


But I believe that the point here is that while there's no real reason that our code can't be fixed to comply with changes to the compiler, there's no justification in the compiler changes finding errors/warnings in the code headers that are the standards everything else is supposed to be based on, unless the fine folks at GNU are going to update those for us all at the same time. :sad: …on the other hand, maybe this is a precursor to that happening…
21 Aug, 2007, Guest wrote in the 14th comment:
Votes: 0
static char *var = "TERM=vt100"; <—- Generates the same conversion warning. This isn't going to cut it :P
21 Aug, 2007, Mister wrote in the 15th comment:
Votes: 0
ack, sorry, I meant:

static char var[] = "TERM=vt100";
21 Aug, 2007, Dorian wrote in the 16th comment:
Votes: 0
Samson said:
Well if the codebase can be updated and not bother one_argument, it won't be quite so bad. But…..

argument = one_argument( argument, arg );

clearly DOES try to write to the string. If it's a const then won't the compiler come down on you for trying to write to read-only strings?


No, it clearly doesn't write to a string. You're confused about const semantics. This is how it works:

char dummy[] = "Hello";
char *a = dummy;
const char *b = dummy; //Points to a const char
char * const c = dummy; //A const pointer to a char
const char *const d = dummy; //A const pointer to a const char

*a = 'A'; //Legal
*b = 'B'; //Illegal, b points of a const char
*c = 'C'; //Legal, c is a const pointer to a char, so it can modify the contents
*d = 'D'; //Illegal, d points of a const char

b = b+1; //Legal, b points to a const char, but you can reseat the pointer
c = c+1; //Illegal, c is a const pointer, so it cannot be changed


In the case of the argument pointer, you would just make it a pointer pointing to a const char. You can see modify where the pointer is pointing to, but not what the contents of the memory it points at. one_argument statement only reseats the pointer; it does not modify the memory contents, which would be illegal.

Quote
So. If this is such a scary problem is there a reason even the C/C++ libraries contain these ghastly mistakes? :)


C++ has already squashed a lot of these problems. C++ string literals are const char[] by definition. Moreover, if you look at the C library in C++, you'll notice a few C string functions, like strstr (I think), return a const char * instead of a char * in C. Still some holes, but it's getting better.

C is a different beast with a different history. Many components were developed years ago with bad implementation, which is now starting to bite all our asses. It's not that people didn't know; rather, no one tried to fix it. Take gets. I still see it used, but it's been bashed on comp.lang.c for years.
21 Aug, 2007, Guest wrote in the 17th comment:
Votes: 0
Dorian said:
Samson said:
Well if the codebase can be updated and not bother one_argument, it won't be quite so bad. But…..

argument = one_argument( argument, arg );

clearly DOES try to write to the string. If it's a const then won't the compiler come down on you for trying to write to read-only strings?


No, it clearly doesn't write to a string. You're confused about const semantics.


The compiler disagrees with you then. I tried to "fix" the problem by making the do_fun format into void do_fun( CHAR_DATA *ch, const char *argument ) and all I got back were complaints upon complaints about the same kind of "illegal conversions" or whatever GNU decided they want. Attempting to correct for it was leading down a path that few of us will have time to pursue. So when 4.2 comes along it's likely that those of us with better things to worry about will be forced to suppress this crap instead of "fixing" it.
21 Aug, 2007, Guest wrote in the 18th comment:
Votes: 0
On a semi-related note in all this, this function was written for me by Noplex awhile back and I was just wondering if it's good as is or if it needs help, or if there's a better way to do this. It operates just like one_argument and will understand quotes around parts of the argument.

vector < string > vector_argument( string arg, int chop )
{
vector < string > v;
char cEnd;
int passes = 0;

if( arg.find( '\'' ) < arg.find( '"' ) )
cEnd = '\'';
else
cEnd = '"';

while( !arg.empty( ) )
{
string::size_type space = arg.find( ' ' );

if( space == string::npos )
space = arg.length( );

string::size_type quote = arg.find( cEnd );

if( quote != string::npos && quote < space )
{
arg = arg.substr( quote + 1, arg.length( ) );
if( ( quote = arg.find( cEnd ) ) != string::npos )
space = quote;
else
space = arg.length( );
}

string piece = arg.substr( 0, space );
strip_lspace( piece );
if( !piece.empty( ) )
v.push_back( piece );

if( space < arg.length( ) - 1 )
arg = arg.substr( space + 1, arg.length( ) );
else
break;

/*
* A -1 indicates you want to proceed until arg is exhausted
*/
if( ++passes == chop && chop != -1 )
{
strip_lspace( piece );
v.push_back( arg );
break;
}
}
return v;
}
21 Aug, 2007, Dorian wrote in the 19th comment:
Votes: 0
Samson said:
Dorian said:
Samson said:
Well if the codebase can be updated and not bother one_argument, it won't be quite so bad. But…..

argument = one_argument( argument, arg );

clearly DOES try to write to the string. If it's a const then won't the compiler come down on you for trying to write to read-only strings?


No, it clearly doesn't write to a string. You're confused about const semantics.


The compiler disagrees with you then. I tried to "fix" the problem by making the do_fun format into void do_fun( CHAR_DATA *ch, const char *argument ) and all I got back were complaints upon complaints about the same kind of "illegal conversions" or whatever GNU decided they want.


Are you sure?

Quote
dan@ubuntu:~$ cat > test.c
void func( const char *ptr ) { }

int main(void) { func("test"); return 0; }
dan@ubuntu:~$ gcc -Wall -Wwrite-strings -o test test.c
dan@ubuntu:~$ gcc –version
gcc (GCC) 4.1.2 (Ubuntu 4.1.2-0ubuntu4)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

dan@ubuntu:~$


My gcc is not complaining. I even bumped it up to C99 and it still worked. Did you update the function pointer typedef as well? Like you point out, this isn't a quick fix. It's an easy fix, but certainly not a quick one.
21 Aug, 2007, Guest wrote in the 20th comment:
Votes: 0
The compiler also complained about assignments to read-only strings in the originating call for one_argument. Hence why I'm looking toward std::string to solve my own problems. I think this whole thing is ludicrous. I can only imagine what much larger projects will go through when their turn at the hammer comes.
0.0/28