[RM2K3] [DYNRPG] EDGE CASE BUG: EMPTY COMMENT LINES
Posts
Pages:
1
I ran into an interesting and sneaky bug in a DynRPG project, and I thought it worth sharing here. When I dropped my DynParams plugin into my game project and tried to run it, I got an error message about a request to terminate in an unusual way, and then the game crashed. I used some Message commands to trace where the crash was happening, and found that it occurred in the middle of a bunch of Comment lines, which of course should do nothing. o.O I narrowed it down further and found that the culprit was a completely empty Comment line, which I'd used for visually separating one set of Comments from another.
In the C++ code for DynParams, I had an onComment implementation like this:
It turns out that if the Comment line is empty, the function argument "text" will be NULL, which causes trouble if you try to initialize a string with the =operator using it. My solution looked like this:
This is, perhaps, more a general C++ thing than a DynRPG thing--make sure your char array isn't NULL when trying to feed it into a std::string--but it came up because I wasn't keenly aware of how onComment handles the case of an empty Comment line, and it's the sort of thing that can easily slip past testing and give your plugin a bad rap because it caused somebody's game to crash. Watch out!
And of course, if you downloaded DynParams before now, you may want to get a fresh copy. I also fixed a couple things in the readme file.
In the C++ code for DynParams, I had an onComment implementation like this:
bool onComment( const char* text,
const RPG::ParsedCommentData* parsedData,
RPG::EventScriptLine* nextScriptLine,
RPG::EventScriptData* scriptData,
int eventId,
int pageId,
int lineId,
int* nextLineId )
{
std::string commentText = text;
/* more stuff */
}
It turns out that if the Comment line is empty, the function argument "text" will be NULL, which causes trouble if you try to initialize a string with the =operator using it. My solution looked like this:
bool onComment( const char* text,
const RPG::ParsedCommentData* parsedData,
RPG::EventScriptLine* nextScriptLine,
RPG::EventScriptData* scriptData,
int eventId,
int pageId,
int lineId,
int* nextLineId )
{
std::string commentText;
if( NULL == text )
{ // Comment text is empty
commentText = "";
}
else
{ // Comment text is non-empty
commentText = text;
}
/* more stuff */
}
This is, perhaps, more a general C++ thing than a DynRPG thing--make sure your char array isn't NULL when trying to feed it into a std::string--but it came up because I wasn't keenly aware of how onComment handles the case of an empty Comment line, and it's the sort of thing that can easily slip past testing and give your plugin a bad rap because it caused somebody's game to crash. Watch out!
And of course, if you downloaded DynParams before now, you may want to get a fresh copy. I also fixed a couple things in the readme file.
Hmmm. Very interesting. Makes sense I guess though. It's funny, because I've always ignored the "text" parameter of that function entirely. I forget who wrote this technique originally (probably Kazesui), but this is probably a safer way to get a comment command anyway:
I wouldn't check for the entire comment text otherwise though, because it'll just check every time there's a comment. You could easily do "@command_to_check "here's some text to check for."
bool onComment( ... )
{
// parsedData already stores a parsed verison of the command, so you can use it here
std::string cmd = parsedData->command;
// cmd.compare() will evaluate to 0 (false) if cmd matches the given text ("my_command" in this case).
// It sounds a little counter-intuitive, but that's how .compare() works.
// The "!" is a cleaner way of writing "if ____ is false" or "if ____ is 0"
// parametersCount ensures there is a certain number of parameters before it runs any more code... thus preventing any sort of crashing.
// If parameters are optional, use "parameterCount <= #"
if(!cmd.compare("my_command") && parsedData->parametersCount == 2)
{
// stuff here...
return false; // prevents any additional code from running during this cycle.
// Removing this line is not a good idea because your plugin could take a performance hit depending on how many comment commands
// you're checking for in your plugin
}
return true;
}
I wouldn't check for the entire comment text otherwise though, because it'll just check every time there's a comment. You could easily do "@command_to_check "here's some text to check for."
Pages:
1














