Randomly changing variable
23yrold3yrold

Can we please brainstorm for a minute why an integer variable might spontaneously reset to zero? This thing gets explicitly assigned nowhere but in a SetState() function, which does not allow 0 to be assigned to it. Elsewhere, I have code to check if the value is ever equal to 0, and it occasionally is. The only reason I can think of that that might happen is if there's sort of buffer overrun out of an array, but this variable is cushioned by a large number of other single variables (ie: it's nowhere near an array in memory), and this happens in multiple objects. So I guess it's unlikely, but I can't think of what else might do that. Any other ideas?

Onewing
Quote:

So I guess it's unlikely, but I can't think of what else might do that.

Neither can I. What all debugging process have you tried?

nonnus29

Sleep on it. Repeat if necessary. :P

BAF

Optimizations? Did you try disabling optimization or declaring it volatile?

GullRaDriel

Sometimes a buffer overflow fill variables with some strange values. The last pointer problem I had was caused by such a thing. ptr = NULL ; if( ptr == NULL ) do nothing ; but ptr wasn't NULL as a for() loop with a char toto[it] overwritten it.

Launch GDB, set a breakpoint at main, and go step by step, check the variable value.

Try launching your code trough valgrind.

Kris Asick

The first thing that comes to mind is you've done something like this:

void SetVarible (int var)
{
  var = 1;
}

void main (void)
{
  int v;
  SetVariable(v);
}

When you pass a pointer or variable to a function, it is copied into the function. If you want to change the value of a variable passed to a function, you need to make it a reference like this:

void SetVarible (int &var)

This counts for pointers as well. If you want to change where a pointer passed to a function is pointing to it needs to be a reference to a pointer.

If you don't make it a reference, any changes you make to the variable/pointer will only affect said function.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Sirocco

My vote goes for a buffer over/under run, or a boofed pointer. If all else fails look for uninitialized variables.

CGamesPlay

Valgrind would spot this in a few seconds ;)

miran
Quote:

Elsewhere, I have code to check if the value is ever equal to 0, and it occasionally is.

Does that code look like this:

if (evil_variable = 0) {
   printf("OMFG!");
}

?

BAF

Well that wouldn't work. blah=0 always returns 0, which is false.

miran

Oh right... :-[

EDIT:

What about this:

if (evil_variable = 0) {
   printf("OMFG!");
}

// then somewhere else

if (evil_variable == 0) {
   printf("OMFG!");
}

:D

BAF

That would work. :D

Kitty Cat

GDB has a way to watch memory addresses, so you can set a watchpoint on the variable's location, run the program, and it'll break whenever the memory is changed.

Richard Phipps

My vote goes for a bad pointer too!

KC's suggestion to find the problem sounds good too.. :)

Thomas Fjellstrom

My vote goes for bad pointer plus memory-corruption/buffer-overflow.

23yrold3yrold
Quote:

Did you try disabling optimization or declaring it volatile?

It's not volatile. No special optimizations.

Quote:

When you pass a pointer or variable to a function, it is copied into the function.

Nah, I ain't that amateur. ;) The value is a private member that gets set nowhere except in its own private Set() function (one that checks for a value of 0, too). I assign to it nowhere else, but I reference it every loop and occasionally discover it's 0.

Quote:

If all else fails look for uninitialized variables.

Not that. I'm picky about always initializing.

Quote:

Does that code look like this:

Actually, I just output the variable to file. Says 0.

I'm still cleaning up the code and making sure there's no dirty hacks that might be doing this, so maybe it'll disappear on its own. To my shame, I'm not much of a debugger, I could never get stuff like GDB to work, so I don't know if I'll have to resort to that. Main thing that concerned me was if there was something else I hadn't though of, so I'll have to check all my array crap.

Quote:

Try launching your code trough valgrind.
....
Valgrind would spot this in a few seconds ;)

You Linux people can kiss my butt. ;)

Richard Phipps

You could try Fortify. It's free and you can use it with GCC or MingW on Windows. I managed to get it working before, so you should have no problem.. ;)

Onewing

Most debuggers have a way to watch variables, even break once the variable changes. You can't just look through X amount of code and think that you've solved the problem manually.

What IDE are you using?

23yrold3yrold
Quote:

You can't just look through X amount of code and think that you've solved the problem manually.

If the variable stops reporting 0 after the code is finalized, I can be reasonably certain. :)

Quote:

What IDE are you using?

MinGW and SciTE.

I'll look into Fortify if I find the need.

Michael Jensen

This will totally fix it:

if (myvar==0)
{myvar=1;}

Obviously, you didn't read Worse Than Failure today...

:D

23yrold3yrold

That's basically the current remedy and it works fine, but I prefer knowing how it happened in the first place ...

Michael Jensen

Well, at least I made myself laugh -- I guess that's all that matters. 8-)

Kris Asick

Well, depending on the amount of code between when you set it to non-zero and when it gets mysteriously reset to 0, you could always do something like this to try and spot where exactly it changes:

void DoStuff (void)
{
  allegro_message("A: Value = %d",myVar);
  myVar = 1;
  allegro_message("B: Value = %d",myVar);
  // next command goes here
  allegro_message("C: Value = %d",myVar);
  // next command goes here
  allegro_message("D: Value = %d",myVar);
  // next command goes here
  allegro_message("E: Value = %d",myVar);
  // next command goes here
  allegro_message("F: Value = %d",myVar);
  // next command goes here
}

It would be nice to see some code. Specifically, I want to see the code for where the variable is created, because my next suspicion is out-of-bound array access.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Richard Phipps

If this is a game, maybe display the contents of the variable every frame and see if any parts the game logic chnage it. If it changes straight away then it's probably something in your inner loop.

james_lohr

Are you using any sort of multi-threading?

Otherwise make a backup of your project, and then start ripping out chunks of it until the problem goes away. It's probably wise to find out what it is while it's occuring regularly. When you have the same problem, but it only occurs once a week - that is when you start getting worried.

nonnus29

I never use debuggers either, just use printf or system.out.println, or whatever. But this article made me realize that being proficient using debugging tools can give you much powerful programming mojo:

Clickie

spellcaster
Quote:

Well, depending on the amount of code between when you set it to non-zero and when it gets mysteriously reset to 0, you could always do something like this to try and spot where exactly it changes:

Geez!
People, this is 2007. Learn to use a debugger. I know that gdb seems intimidating first, and that there is no free frontend for it on windows, but for a case like this all you need is too google for a howto, run the game with debug info through gdb and take a look at the callstack.

Writing to a log is nice to get a log. It's not a good debugging method. Use it to realize that there is an error, don't use it to hunt it down.

Quote:

I never use debuggers either, just use printf or system.out.println, or whatever.

Using a debugger saves you a lot of time. if you consider yourself a coder, learn how to use a debugger. The 2 hours spent learning the basics of gdb (or the 0.5hours if you're using a debugger with a modern frontend) will be nothing in comparison to the time saved looking for a bug.

Learn to use your tools. For a c/c++ coder these tools are:
editor
compiler
debugger

CGamesPlay

Without Valgrind, mine and BAF's TINS '07 entry would never have been submitted. It's just that good.

james_lohr

A debugger is to programming as God-mode is to gaming. :P

Quote:

the 2 hours spent learning the basics of gdb

Dev-C++ comes with gdb all ready to go. You just have to click a few buttons in the IDE. Still, I prefer only to enable God-mode when absolutely necessary ;)

Richard Phipps

MSVC's debugger is handy, it useful catches some bound errors and uninitialised variables. The only problem I've found is that it really slows down when doing even a few new objects using a STL list container.

spellcaster
Quote:

A debugger is to programming as God-mode is to gaming.

In that case I recommend that you code using copy con. Those fancy editors are pretty close to cheating either, eh?

I hope you meant this as a joke. If not, I hope you don't consider a job where you have to code or interact with coders.

Paul whoknows
Quote:

A debugger is to programming as God-mode is to gaming. :P

I rarely use debuggers, I use logfiles and I watch all the important variables using text_printf_ex instead. Is something wrong with me? ???

CGamesPlay
Quote:

Is something wrong with me?

Not until you start working on large projects. Seriously, after a few days wasted debugging like that you will invest the time to learn a debugger.

Paul whoknows

Ok, I'll start right now.

james_lohr
Quote:

I hope you meant this as a joke. If not, I hope you don't consider a job where you have to code or interact with coders.

Of course I was only teasing. :)

There are plenty of things you simply can't identify without a debugger, no matter how badly you pollute your code with log messages.

Myrdos

I first started using gdb to quickly debug crashes:

1) Compile your code with the -ggdb option

2) Use "gdb myprogram.exe" to debug it

3) Use the gdb "run" command to start your program. You can enter any command line arguments here. "run -res 640x480"

4) Use the "backtrace" command to figure out where the crash occurred. This will tell you the line number of the crash, where this function was called from, and where the calling function was called from, and so on all the way to your main program.

There are plenty of other options that you can find using the "help" command, but these simple steps have alone have saved me countless hours of time.

I find that no bug can withstand the combined might of good coding style and gdb.

Jakub Wasilewski
Quote:

There are plenty of other options that you can find using the help command, but these simple steps have alone have saved me countless hours of time.

After learning to use that, the next step should be learning how to use bt (backtrace), up, down and print together. After learning those, you'll be able to nail 99% of all bugs in no time.

For your problem, all you have to do is type 'tbreak <filename>:<linenumber>', with filename:line set to somewhere where the variable that is randomly changing is in scope - this will make the program stop once when it reaches that point. Run the program until it stops.

Then, type 'watch <name_of_the_variable>' and the program will stop whenever the value gets changed.

You can use 'cont' to continue if it's not the overwrite you were looking for (that is, it's happening inside the Set() method, which you can check with the 'bt' command).

nonnus29

Here's a tute, I have a wierd little bug in my compiler/parser to practice on too...

:D

23yrold3yrold
Quote:

Are you using any sort of multi-threading?

No. It's a little difficult to rip it apart though; lots of classes that talk to each other and make isolating large chunks of code impractical.

Quote:

Dev-C++ comes with gdb all ready to go.

And that's the only nice thing you'll ever see me say about it. ;)

And yes, like I said it's to my shame I never really learned a debugger. I did try GDB a long time ago but never really got it working well. I still think this bug will just go away once the code's all cleaned up, but nonnus posted a nice looking link; guess I owe it to myself to read up. Or maybe look into Fortify.

Shame there isn't a site like the GotW for debuggers. Here's some source code for a simple program, here's a weird bug in the program, find the bug and fix it. Little exercises like that for noobs like me. :)

BAF

I had to hack at Fortify to get it to even compile under mingw. After I did, though, it worked well.

Edgar Reynaldo

You can download a pdf manual for gdb here:
http://www.gnu.org/software/gdb/documentation/
And download the latest version here:
http://www.gnu.org/software/gdb/download/

I think these commands could spot your problem right away.
cmd->gdb filename.exe
1. Set a breakpoint at the beginning of your main function.
gdb->break filename.srclanguage:line_number
2. When you reach that breakpoint , set a watchpoint on your mystery variable
gdb->rwatch mystery_variable
3. Then set a condition on that breakpoint(rwatch is also a breakpoint) to notify
you when your variable has reached a certain value.

  1. is the breakpoint number of your rwatch breakpoint

gdb->condition # mystery_variable == 0

This will stop the program as soon as mystery_variable becomes 0.
Then use:
gdb->bt full

This should tell you more than enough to fix your program.

8-)

Thread #591565. Printed from Allegro.cc