Sign in to follow this  
Kest

Code demons again (real this time). Memory molestations.

Recommended Posts

My project has began randomly crashing at a certain function, on a specific line of code. The problem doesn't make any sense. I was assigning a const reference to an array node, then on the very next line, trying to use it - which is bringing up an access violation. The only insane possible thing that could have been happening was that memory was being molested outside of my code. But how could memory be modified outside of my code that effects the exact same two lines of code in my project every time I tested it? And I've got it to cause the violation about 10 times so far. The final time, I tried something crazy. Right under the assignment operation (setting the const reference to the array node), I checked to make sure it was still assigned. I checked to make sure six times in a row. Guess what? The 5th check failed on that test. Here's a snapshot. My _V() function just throws an error if the passed value is false. After the error occurs, the reference address is incorrect. But the original array node is still fine. Does anyone know what could cause this? I've never seen anything like it before. I'm also running a new divx encoding program in the background. That couldn't have any effect on the memory of my application, could it? I mean without throwing it's own access violation? Thanks for any help

Share this post


Link to post
Share on other sites
You're doing something wrong, not some other app. You're running in your own address space, and nothing else is touching it.
You're writing out of array bounds somewhere, or trying to write to released memory or an uninitalized pointer.

Share this post


Link to post
Share on other sites
Quote:
Original post by tok_junior
You're doing something wrong, not some other app. You're running in your own address space, and nothing else is touching it.
You're writing out of array bounds somewhere, or trying to write to released memory or an uninitalized pointer.

Then how is memory changing in between two lines of code that doesn't modify any memory?

The verification code is exactly equal to if( &ref != &array.node[e] ) Error();

How could calling this code six times cause memory to change on the fifth call?

Share this post


Link to post
Share on other sites
Just a uneducated guess, but it seems to me the problem is either in KCharAnim::GetEvents() or KCharAnim::GetEvents().Get(e)... Any reason why it wouldn't be??

Cheers
-Scott

Share this post


Link to post
Share on other sites
Set a memory breakpoint and determine when it fires.

This might be a symptom of using memory which used to be valid, but has since been deallocated (as would be the case when returning by reference a stack variable).

Share this post


Link to post
Share on other sites
Quote:
Original post by Kest
The only insane possible thing that could have been happening was that memory was being molested outside of my code.

Then maybe it's not an insane thing that happens. Maybe you just have a bug in your code.


Quote:
That couldn't have any effect on the memory of my application, could it? I mean without throwing it's own access violation?

No. It runs in its own memory space. There's no one but your own process to blame, I'm afraid.

Share this post


Link to post
Share on other sites
Quote:
Original post by popsoftheyear
Just a uneducated guess, but it seems to me the problem is either in KCharAnim::GetEvents() or KCharAnim::GetEvents().Get(e)... Any reason why it wouldn't be??

Because both are just inlined code returning variables.

Quote:
Original post by ToohrVyk
Set a memory breakpoint and determine when it fires.

This might be a symptom of using memory which used to be valid, but has since been deallocated (as would be the case when returning by reference a stack variable).

But as I mentioned, the original array node is still intact. Only the reference is incorrect. The reference that is set one line above the crash point. Is there a way to set a memory breakpoint on a reference variable that is declared one line above where it causes the problem? The function is called thousands of times before it randomly throws this memory access problem, and each time, the reference variable has a new address.

Share this post


Link to post
Share on other sites
Quote:
Original post by Spoonbender
Quote:
Original post by Kest
The only insane possible thing that could have been happening was that memory was being molested outside of my code.

Then maybe it's not an insane thing that happens. Maybe you just have a bug in your code.

I'm open to clues. What kind of bug would it be? I don't use more than one thread for any of my own routines. How could that memory change between two lines of code that is repeated 4 times before it?

Share this post


Link to post
Share on other sites
Quote:
Original post by Kest
I'm open to clues. What kind of bug would it be? I don't use more than one thread for any of my own routines. How could that memory change between two lines of code that is repeated 4 times before it?


It wasn't modified between those two lines. It was likely corrupted much earlier. Memory stomping bugs are evil for precisely this reason. Just because memory is corrupted doesn't mean the application will crash; it might run forever just fine and all you'll see is wierd un-reproducible bugs in your application; it might crash.

It's also perfectly fine to read bad memory, it's just not ok to write to it.

So couple things to look for:

1) any place in your app where you are iterating over an array, make sure you are properly checking for out of bounds
2) any place where you are using C-strings instead of std::string
3) any place where you are using a pointer that wasn't first initialized to NULL

-me

Share this post


Link to post
Share on other sites
Quote:
Original post by Moomin
Does the function being called alter any memory?

It's stack-based memory that is being changed. So if I'm not mistaken, everything that executes is altering it. Even parameter values being sent to functions is altering stack memory. Right?

But to answe the question, no. No functions are modifying any memory other than stack memory after Anim_FindFirstEventHaltPoint() is called and before the access violation.

And all of these related functions have been in place for many months. I only first encountered the problem a few hours ago.

Share this post


Link to post
Share on other sites
Quote:
Original post by Palidine
It wasn't modified between those two lines.

Yes, it was. The value of the stack variable reference actually literally changes in between those two lines of code. Whether it is changing because of a bug that happens earlier is unknown to me. But that reference is the only thing that's clearly wrong.

The problem is still occuring after a complete rebuild. Here's another test. Check out the watch-window values of the pointers. Both are different, and both are incorrect:

Share this post


Link to post
Share on other sites
can you show the code for the Get method? Is it popping off a stack or something?

Also, any chance you are running in release instead of debug?

-me

Share this post


Link to post
Share on other sites
Quote:
Original post by Palidine
can you show the code for the Get method? Is it popping off a stack or something?

Also, any chance you are running in release instead of debug?

The function belongs to a templated class. < type > is the only template variable:

const type& Get(int index) const{ return *Refs[index]; }

I'm in debug. The access violation actually first occured when I ran it outside of the debugging environment.

Quote:
Original post by _Sigma
Are you sure GetCount() in your for loop is returning the proper value?

The value of e is 1 in the first snap shot. The array size is 2. Also, array[1] is a valid index and has the correct values. Only the reference is wrong. Even if I was trying to reference outside of the arrays bounds, the address value of array[1] and the reference variable address should still match.

Share this post


Link to post
Share on other sites
So it sounds like another application can't change memory in the stack that effects my program. My code also uses only one thread to execute. What about other threads that run with my program? Such as the timer, directx, or etc? Is it possible that some part of my code is ripping on them - such as changing the address of one of their pointer variables - causing them to modify it and change something of mine? Or is that also impossible? Is there similar protection between threads that exists between programs?

Share this post


Link to post
Share on other sites
Quote:
const type& Get(int index) const{ return *Refs[index]; }


What is Refs?

Who allocates it, what does its subscript operator do, are the elements dynamically allocated, ....

Share this post


Link to post
Share on other sites
Quote:
Original post by DrEvil
post GetEvents

Ahhhh crap..

Damn!

*Hangs head in shame*

GetEvents() was supposed to return a const reference to the array object. Instead, missing the & operator on the return value, it was returning a copy of it.

I can't believe this code has been running for months like this.

Thank you DrEvil, I am royally indebted to you. If there's anything I can do to return the favor, let me know. You probably just saved me a week.

Is there any way to avoid these types of typos? I could have more right now. Shouldn't the compiler warn about storing a copy of something being returned from a function into a reference variable?

Thanks again for your simple and insanely useful reply.

edit:

There's still one thing I don't understand, though. If there was a new copy being generated every time I called GetEvents(), then how did the first five validation checks succeed? Did it just happen to copy the array object over onto the same memory the first five times?

edit 2:

Uhh, I should also give thanks to popsoftheyear. If I would have looked more closely after his suggestion, I would have found it.

[Edited by - Kest on August 13, 2007 5:59:49 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Kest
Is there any way to avoid these types of typos? I could have more right now. Shouldn't the compiler warn about storing a copy of something being returned from a function into a reference variable?


Nope. It's perfectly valid code. If something is already being returned by value (i.e. a copy) then you might want a reference to it if you're just doing local stack work. Otherwise, you'd incur 2 copies when you just need one.

-me

Share this post


Link to post
Share on other sites
Normally I get warnings on problems like that. (MSVC2005)

warning C4172: returning address of local variable or temporary

Are you sure you aren't getting this warning?

Edit: nevermind, depends on how its set up. If your function returns a copy and you are catching it in a reference that doesn't seem to produce this warning. Seems like a no brainer that it should. pos. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Palidine
Quote:
Original post by Kest
Is there any way to avoid these types of typos? I could have more right now. Shouldn't the compiler warn about storing a copy of something being returned from a function into a reference variable?


Nope. It's perfectly valid code. If something is already being returned by value (i.e. a copy) then you might want a reference to it if you're just doing local stack work. Otherwise, you'd incur 2 copies when you just need one.

-me

But the copy is being sent into the abyss, right? The function returns a copy, I assign it to the reference variable, then the copy is chucked into the recycler. Isn't that always going to end badly?

Quote:
Original post by DrEvil
Normally I get warnings on problems like that. (MSVC2005)

warning C4172: returning address of local variable or temporary

Are you sure you aren't getting this warning?

No, and I'm using warning level 4. Are there any specific reasons it would ignore the warning? I need to purposely test it a few times to see if it always ignores it.

edit after your edit: That sucks.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kest
But the copy is being sent into the abyss, right? The function returns a copy, I assign it to the reference variable, then the copy is chucked into the recycler. Isn't that always going to end badly?


No. when objects go out of scope they get their destructor called. there are plenty of times you let objects die on the stack. For instance:


class Vector
{
float x;
float y;
float z;
};




that's an object that you often return by value:


Vector toTarget = target.pos - my.pos;

//do some stuff with toTarget

//exit scope




Vector is returned by value (copy) from the operator-

[EDIT: that warning is for returning the address of an internal stack variable:


Vector *getVector()
{
Vector theAnswer;
return &theAnswer;
}



that's bad because theAnswer is destructed right after returning it's ponter.]

-me

Share this post


Link to post
Share on other sites
It's caught properly there. The compiler ought to be smart enough to error/warning on something like this

const Vector &toTarget = target.pos - my.pos;


I can't think of any situation this would be anything other than a bug.

Edit: Palidine, I don't see how you're example is relevant. I think his quote is spot on. Catching something returned by value in a reference is a no win situation. Stoopid compilers ought to be able to catch these sort of things.

Share this post


Link to post
Share on other sites
Quote:
Original post by Palidine
Quote:
Original post by Kest
But the copy is being sent into the abyss, right? The function returns a copy, I assign it to the reference variable, then the copy is chucked into the recycler. Isn't that always going to end badly?


No. when objects go out of scope they get their destructor called. there are plenty of times you let objects die on the stack. For instance:
....

-me

I don't get it. I know it's perfectly valid to return copies. I'm asking why it's okay to store those copies excusively into a reference variable, straight from the called function. This would be okay:

ref = copy = FunctionReturningCopy();

But this also seems to be okay:

ref = FunctionReturningCopy();

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this