My code, (MCB2300 and RL-ARM) which parses a file on SDcard for execution commands, was working fine (theoretically) until today it's being thrown into the Undef_hander. If I make small modificatons to the source, it happens at different points in parsing, so it's not a hard error in the input. I can't find anything in the forums or docuementation on what throws this error. I've tried looking at stacks, etc. to no avail. It seems to happen in ftell() but I haven't pinned it down yet. Anyone have any insights?
So what have you changed?
Memory overwrites - out-of-bounds array accesses, stack overflows or use of invalid memory pointers (uninitialized or NULL pointers from failed allocation) can give you this issue.
A simple change such as adding os_dly_wait(50) or printing a debug statement out the serial port changes where it fails. I then thought timing problem, but further changes to the size of the delay cause no change. I went into RTX_Conf_LPC23xx.c and tried altering the OS_STKSIZE, and just inc case the OS_FIFOXZ to no effect. There is one stack in the file manager task (stolen from SD_FILE example) that I increased as well. Still no change.
If you have access to a static code analyzer, that is a good place to start.
I am willing to help you - if you can put your code (.zipped) online somewhere.
Thanks. Can I just send to your email? If you don't want to post that, send me a private message at daver@birket.com
For anyone else who might be listening, I've tracked the problem down to the statment
char parse_parameter( char ** String_pp ) { char state = 0; char ch; char * tag_p, *nametype_p, *nameindex_p, *condition_p; BOOL result;
// we have already read the < part of the tab, process until ending tag tag_p = (char*)&XML_TAG[0]; nametype_p = (char*)&NAME_TYPE[0]; nameindex_p = (char*)&NAME_INDEX[0]; condition_p = (char*)&CONDITION_TAG[0]; *tag_p = 0; // clear them out *nametype_p = 0; *nameindex_p = 0; *condition_p = 0; state = 0; ch = 0; do { switch (state) { case 0: // just coming in, get the tag
It dies (dumps to Undef_handler) at the switch(state) statement
Try to tag source code using the proper tags.
char parse_parameter( char ** String_pp ) { char state = 0; char ch; char * tag_p, *nametype_p, *nameindex_p, *condition_p; BOOL result; // we have already read the < part of the tab, process until ending tag tag_p = (char*)&XML_TAG[0]; nametype_p = (char*)&NAME_TYPE[0]; nameindex_p = (char*)&NAME_INDEX[0]; condition_p = (char*)&CONDITION_TAG[0]; *tag_p = 0; // clear them out *nametype_p = 0; *nameindex_p = 0; *condition_p = 0; state = 0; ch = 0; do { switch (state) { case 0: // just coming in, get the tag
If XML_TAG, NAME_TAG, ... are just normal character arrays, then you don't need to take the address of the first element. Just use the name of the arrays directly. If they are not global arrays - are you sure they have valid addresses so your pointers gets assigned addresses that do point to writable memory?
And if you do have a stack overflow, then your assigns to your auto variables can each represent an overwrite of something more important somewhere else.
By the way - do this code run in RAM or in flash? If run in flash, then the switch statement shouldn't be able to go wrong. Unless there is an hidden helper function used, and you have a stack overflow making this helper function return to a random place. Or this helper function corrupts some data involving any interrupt.
All: Thank you for your input, it was an array access out of bounds caused by an error in the input file. The problem was the debugger just wasn't letting me see it. I don't know why it died at the switch statement, the actual fault was considerably further downstream. I had to fall back on the good old debugging technique of toggling an LED when I reached a certain point in the code, and then following it until the real fault showed up. I've put more checks in to test the input code...
"I've put more checks in to test the input code..."
That is always a recommended thing to do. Expect everything to fail. So check everything. Even the things that really should not be able to fail - tomorrow you make an unrelated change somewhere else suddenly make it possible to fail ;)
- Check all input parameters for reasonable values. - Check that produced return value seems reasonable before returning it. - Does function documentation actually document above "contract" requirements? - Consider what to do for switch values not covered. - Can any input parameter set result in internal evaluation overflows? - Verify every array access. - Keep depth counter for every recursive function call. - Add timeouts to every wait. - Do functions need parameters that allows global data to be modified? - Is const/static data properly "protected" by being stored in read-only code space? - Is nonvolatile configuration actually valid configuration or garbage or possibly having partial update? - Can "finite" loops fail to exit? - Are every variable given a start value? - Can program get in fight for critical resource? - Can "producer" overrun "consumer"? - Are all "tasks" actually running when they should run? - Are any large variables stored on stack - and is it ok based on stack size and call tree? - Can max "input load" starve main program? Indirectly - can there be external stimuli that makes program to fail even when the device should by specification be able to supply a specific service? ...