













Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
I would make my own version of mysql_safe_query that had the same prototype except it took a const char*, and then that function -- and only that function -- would cast the const char* to a char*. When the compiler looks up the function mysql_safe_query, it'll see the one with char* and the one with const char*, and since its string is a const char*, it knows to pick the right one.
I think that's what you already said, though.
I think that's what you already said, though.



Off the Edge of the Map

GroupAdministrators
Posts1,199
JoinedMar 21, 2006
Something like this?
I don't think I did that right though. >.>
int mysql_safe_query( const char* fmt, ... ) { char *buf; buf[0] = '\0'; buf = str_dup( fmt ); return mysql_safe_query( buf, ... ); }
I don't think I did that right though. >.>


Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
Well don't forget to clean up the memory you allocated. And unfortunately it's not quite that easy since you can't "pass" the ... to the other function (well, I don't think so at least). I'm sure it's possible, though, perhaps with some obscure compiler define...
EDIT: oh, and don't write to the zero^th position of buf before allocating memory for it.
EDIT: oh, and don't write to the zero^th position of buf before allocating memory for it.


Off the Edge of the Map

GroupAdministrators
Posts1,199
JoinedMar 21, 2006
Oh, I thought I was clearing it. Hrm.



Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
buf is a char*, so a pointer to memory. buf = 0 is different from buf[0] = 0 -- buf = 0 means set the value of the pointer itself to zero, whereas buf[0] means take the address contained in the pointer buf (which is currently uninitialized), add 0 to it, and then set it to zero. So, buf[0] = 0 for uninitialized buf means that you're writing zero to a byte that is basically random -- sure recipe for crashing.



Off the Edge of the Map

GroupAdministrators
Posts1,199
JoinedMar 21, 2006
Ah,so if I change that to buf = 0 that'll make sure it's clear? or even changing the declaration to char *buf = NULL; maybe?



Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
Well, you could, but since the first thing you do is give it a value (from str_dup) I'm not sure it really matters that much to initialize it.


Off the Edge of the Map

GroupAdministrators
Posts1,199
JoinedMar 21, 2006
void stralloc_printf( const char **pointer, const char *fmt, ... ) { char buf[MSL * 4]; va_list args; va_start( args, fmt ); vsnprintf( buf, MSL * 4, fmt, args ); va_end( args ); STRFREE( *pointer ); *pointer = STRALLOC( buf ); return; }
Am I looking to need to do something like the above for this? in a way? maybe?



Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
To be honest I've not really worked with varargs that much, so I'd have to look up the docs, but I don't think that would do the trick -- you don't want to do the vararg handling yourself, you just want to pass it along to the mysql query function.



Conjurer

GroupMembers
Posts395
JoinedMar 8, 2005
THIS is one of the main reasons I now **!@$!# HATE $#$@$!** programming in C.
You can't pass varargs along to another function, but you CAN pass a va_list along, provided the called function doesn't muck with it. So, you could create TWO interfaces that both call a third function that expects to get a va_list, if you needed two interfaces.

You can't pass varargs along to another function, but you CAN pass a va_list along, provided the called function doesn't muck with it. So, you could create TWO interfaces that both call a third function that expects to get a va_list, if you needed two interfaces.
int mysql_safe_query( const char * fmt, ... ) { va_list args; char *buf = NULL; int rv = 0; buf = str_dup( fmt ); va_start( args, fmt ); rv = mysql_private_query( fmt, args ); va_end( args ); STRFREE( buf ); return rv; } int mysql_private_query( char * fmt, va_list args ) { char buf[MSL * 4]; /* Now, in here you don't do va_start or va_end, that's already done by the caller */ vsnprintf( buf, MSL * 4, fmt, args ); /* and do whatever you did before down here */ }



Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
Geez, if that's really the only way to do it, then yeah, that's pretty ridiculous. At this point, making it into a macro might be better, even though macros are usually not the best solution.
The macro would be a call to mysql_safe_query except that it would just cast the const char* to a char*. Presumably, the mysql code isn't actually mucking with the query. It seems like a bug that the API isn't const friendly...
The macro would be a call to mysql_safe_query except that it would just cast the const char* to a char*. Presumably, the mysql code isn't actually mucking with the query. It seems like a bug that the API isn't const friendly...


Off the Edge of the Map

GroupAdministrators
Posts1,199
JoinedMar 21, 2006
I don't know that it's necessarily a bug, maybe the MySQL team was just as badly hit by the gcc updates as everyone else, and they haven't released a fix for it yet.
As for the solution, I'm not sure whether to use Quix's approach, or the macro approach David mentioned, mainly because I think I misunderstood the macro approach. As of right now, my (char*) casts for each query allows me to compile, but I'd like a better/safer solution eventually.
As for the solution, I'm not sure whether to use Quix's approach, or the macro approach David mentioned, mainly because I think I misunderstood the macro approach. As of right now, my (char*) casts for each query allows me to compile, but I'd like a better/safer solution eventually.



Off the Edge of the Map

GroupAdministrators
Posts1,199
JoinedMar 21, 2006
Hahahahaha. I'm so retarded.
I do have access to the prototype, and the actual function. This has all been just a wild goose chase because the root mysql_safe_query is in my sql.cpp file. >.>
I do have access to the prototype, and the actual function. This has all been just a wild goose chase because the root mysql_safe_query is in my sql.cpp file. >.>



Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
Well, proper programming should be const safe -- you might be right that it's not a "bug" per se but it means they didn't follow good practices. Coming from the MySQL team that's surprising, but, well ...
And yeah, if you had the function all along, well...
And yeah, if you had the function all along, well...




Sorcerer

GroupMembers
Posts723
JoinedMar 5, 2005
Was this fix applied? I just DLed 1.9 and got this:
make -s smaug Compiling o/imc.o.... imc.c:98: error: `const' qualifiers cannot be applied to `void ()(CHAR_DATA*, const char*)' imc.c:8033: error: `const' qualifiers cannot be applied to `void ()(CHAR_DATA*, const char*)' make[1]: *** [o/imc.o] Error 1 make: *** [all] Error 2



Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
I thought they were. Are you using a completely vanilla download? Could you show the lines in question please?



Sorcerer

GroupMembers
Posts723
JoinedMar 5, 2005
100% vanilla.
98:
8033:
98:
const char *imc_funcname( const IMC_FUN * func );
8033:
const char *imc_funcname( const IMC_FUN * func ) { if( func == imc_other ) return ( "imc_other" );



Sorcerer

GroupMembers
Posts902
JoinedJan 29, 2007
Hmm, that's interesting. Well, the const shouldn't be a qualifier to the IMC_FUN. Not sure why my compiler didn't complain about that...


Off the Edge of the Map

GroupAdministrators
Posts1,199
JoinedMar 21, 2006
My compiler doesn't complain about it either...



Sorcerer

GroupMembers
Posts723
JoinedMar 5, 2005
I'm fairly certain before this fix we had warnings which did not compile due to Werror, and I recommended simply not using Werror.
Now we're getting actual errors.
Now we're getting actual errors.