the first thing to do then is switch on -Wall and -Werror then fix the warnings.
... add -02 to get warnings on unitilised varaibles, which must be the most likely cause as far as I can see.
Doing that on the relevant code finds no uninitialised variables, nor anything else of note.
(There are certain kinds of warnings, due to the kind of C++ code PortablE generates, but nothing that could conceivably cause any kind of problem. e.g. It dislikes all the superfluous 0 parameters added to printf() calls.)
BTW, regarding the stack, my Shell defaults to a huge stack (100KB) so that isn't the cause.
Try removing the printf() and dummy(), and simply having a statically defined string, i.e.: static USED char dummyStr[] = "This is never printed!\n";
You could also try adding const to the above.
Both the printf() and dummy() functions are passed constants, which take up memory and alter the layout of constants & variables in memory. If your code is using an uninitialised variable or overwriting memory that it shouldn't, then the altered layout could allow it to work despite the bug(s).
I wouldn't be to quick with dismissing the possibilty of uninitialised variables. Repeatedly running the same program again and again can cause the same behaviour due to that variable being located at the same location in RAM.
In any case, the top suspects would be: - Uninitialised variables (NOTE: Uninitialised global variables may not be picked up by compiler warnings, even with -Wall) - Writing beyond the ends of arrays, or with a bad pointer (could be calculated incorrectly) - Forgetting to return a value in a function that's supposed to return something (the -Wall compiler option should detect this)
There may be other ways to overwrite variables in memory unintentionally, but these are the ones that I can think of.
Hans
EDIT: Added "USED" to the string declaration code above, so that the optimizer doesn't remove it.
Try ... having a statically defined string, i.e.: static char dummyStr[] = "This is never printed!\n";
I'm not convinced this tells us much, since I can call the dummy() procedure (printf() equivalent) with just NULL & 0 parameters.... but I tried it anyway, without it making any difference. (EDIT: Did not use USED, but no optimisations were enabled.)
Quote:
- Uninitialised variables (NOTE: Uninitialised global variables may not be picked up by compiler warnings, even with -Wall)
I don't usually use global variables, since my code is object-orientated. (Certainly no globals in the relevant code.) E's objects are always initialised to zero (unless you are being perverse), so that can't be the issue.
Quote:
- Writing beyond the ends of arrays, or with a bad pointer (could be calculated incorrectly)
No (manual) pointer arithmetic going on (PortablE discourages it).
But writing beyond ends of arrays IS possible... even plausible given I'm using arrays quite a bit. (However, I have been careful, but maybe I'll have to re-examine this possibility.)
Quote:
- Forgetting to return a value in a function that's supposed to return something (the -Wall compiler option should detect this)
Is it the function with the printf added that fails or the function calling it (or called from it)?
Perhaps the error is a level up or down the heirarchy and you are looking in the wrong place for your unitilised / overwriten varaiable.
Other wise without sight of the code it's hard to think what else to say.
BTW 100kb is *not* a huge stack. Gcc for example needs 200kb plus sometimes more. Try increasing the stackj for gcc itself! You just might have an edge case stack failure there (unliely as low stack for gcc normally omits spurios compiler erros not broken code, but you never know).
I'm not convinced this tells us much, since I can call the dummy() procedure (printf() equivalent) with just NULL & 0 parameters.... but I tried it anyway, without it making any difference. (EDIT: Did not use USED, but no optimisations were enabled.)
Okay, I'm confused now. Earlier you said that dummy(0) did NOT work, but dummy(-1,-1,-1,-1,-1,-1,-1,-1,-1) did.
What do you mean by it not making any difference? Is the behaviour the same as with the dummy printf() call? Or does it fail like it does without your dummy call?
The point of the exercise is to try to see if memory layout is what's allowing it to magically work with a dummy call that does nothing. Other than that, it won't help you track down where things are going wrong.
Quote:
I don't usually use global variables, since my code is object-orientated. (Certainly no globals in the relevant code.) E's objects are always initialised to zero (unless you are being perverse), so that can't be the issue.
Okay. However, compiler warnings probably won't catch uninitialised class variables either. That's because it can't tell in which order you'll call the class methods. I've been caught out by this problem before.
You may need to expand your search beyond the "relevant code." I've had a situation like this where the ultimate culprit was in a totally different source file from where things failed.
I hope that you track down the cause soon. These kind of bugs tend to be very difficult to track down.
@all I need to check this more, but I *did* finally find an uninitialised variable, and initialising it does *appear* to have fixed the problem. (I wonder why -Wall -Werror -O2 didn't report it?).
For the curious, the uninitialised variable was in the procedure that was affected by printf(), but the variable wasn't really used there (but instead was passed to a child procedure where it was used - and where I thought it was misbehaving).
I need to check this more, but I *did* finally find an uninitialised variable, and initialising it does *appear* to have fixed the problem. (I wonder why -Wall -Werror -O2 didn't report it?).
That's good news.
Did you pass the variable by reference (i.e., pass a pointer, not the variable itself)? If you passed it by reference, then...
someFunc(int *someVar);
buggyFunc()
{
int someVar;
someFunc(&someVar);
}
Won't trigger a warning, as it could be a get or initialisation function. Making this trigger a warning would deliver too many false warnings.
By contrast, the following should trigger a warning:
someFunc(const int *someVar);
buggyFunc()
{
int someVar;
someFunc(&someVar);
}
The "const" tells the compiler that the function won't modify someVar, and therefore it should be initialised beforehand.
- Kimmo --------------------------PowerPC-Advantage------------------------ "PowerPC Operating Systems can use a microkernel architecture with all it�s advantages yet without the cost of slow context switches." - N. Blachford
@all Fixing the uninitialised variable has stopped the problem. I would have found it far sooner (and not started this thread), if my attempts to debug it (with printf) hadn't stopped the bug for appearing!
From my rusty knowledge of CPUs & (x86) assembler, I still don't understand WHY code to call printf (even if it was NEVER actually called!) anywhere inside the procedure had any affect on the stack at all.
@Hans I didn't do anything fancy like that, but the uninitialised variables was set & used inside a loop, so perhaps that was too difficult for GCC to understand?
@ChrisH: I come late into this thread but looking at gcc warning options, I see that -Wuninitialized is well explained and is not set with -Wall but with -Wextra.
Another option that could be helpful is -Wwrite-strings (not either set by -Wall or -Wextra).
Fixing the uninitialized variable has stopped the problem. I would have found it far sooner (and not started this thread), if my attempts to debug it (with printf) hadn't stopped the bug for appearing!
its not always easy to guess whats going on, I often do some thing else when go into Zombie mode, better play a game or see movie or sleep on it, it does not help steering at the code for hours.
Quote:
From my rusty knowledge of CPUs & (x86) assembler, I still don't understand WHY code to call printf (even if it was NEVER actually called!) anywhere inside the procedure had any affect on the stack at all.
It did not, it just effect where things where put into RAM. In one case you where lucky whit the universalized data inside the variable.
(NutsAboutAmiga)
Basilisk II for AmigaOS4 AmigaInputAnywhere Excalibur and other tools and apps.
its not always easy to guess whats going on, I often do some thing else when go into Zombie mode, better play a game or see movie or sleep on it, it does not help steering at the code for hours.
I come late into this thread but looking at gcc warning options, I see that -Wuninitialized is well explained and is not set with -Wall but with -Wextra.
Not so, it's enabled by -Wall but only works if optimisation is on too.
(those have -Wunitialised in both -Wextra *and* -Wall, which might even br correct I don't know).