Jump to content
  • Advertisement
Sign in to follow this  
StakFallT

Question about possible heap corruption triggered by flowing into a function call

This topic is 2334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

(Hope this is in the right section...)

I have a question about possible heap corruption that I'm hoping someone could help shed some light on. Basically the situation is this, I have a locally declared (Yes I know, local = stack; however it's declared with new ;) ) pointer-object (compound object) that contains another object (That contains pointers as members). It also has a method (Name isn't really important; it's unique though, not like a dtor or ctor, etc...)

Anyhow, essentially this pointer-object is first filled with data from the return of a function that sets the pointers in the object this object contains. So far so good. I then call a method I have built into this object that does some manipulation; however this method is where the problem occurs.


I know the explanation was kinda dense, hopefully this will help. Think of the layout like this:


enum _Container_Type
{
_Container_Type_Uninitialized;
_Container_Type_A,
_Container_Type_B,
_Container_Type_C,
_Container_Type_Unknown
};

class cContainer
{
public:
some_container_A *Object_A_ptr;
some_container_B *Object_B_ptr;
some_container_C *Object_C_ptr;

_Container_Type Type;
};

class cSomeSmallerObject
{
public:
cContainer *Object_Container_Ptr;

std::string SomeFunction();
};

class cSomeObject
{
public:
std::map<int, cSomeSmallerObject> SmallerObjects;
std::string Name;

std::string SomeFunction(); //Essentially loops through SmallerObjects calling SmallerObject's SomeFunction function. Also where the problem occurs.
};


std::string cSomeObject::SomeFunction()
{
std::string Output;
std::map<int, std::string> OutputComponents;

//...

return Output;
};


<some_return_type> cSome_Class::cSome_Function(blah...)
{
//...

cSomeObject *Object = new cSomeObject();
Object = _GetObject();
Object.SomeFunction(); // <-- Problem function.

return <some object of some_return_type>;
};


Breakpointing on Object.SomeFunction, everything looks great, breakpointing on the first line in that function, still, everything looks great. It's not until it breaks on the second line that the addresses referenced in the Object_Container_Ptr member of the cSomeSmallerObject get messed up; as a matter of fact, not just the addresses but all members in the Object_Container_Ptr object get annihilated. More directly:
Object_A_ptr
Object_B_ptr
Object_C_ptr
Type

And any other members, are all up the creek. And as I said everything works great, even setting the data to that first function call's return, and even making that second call (Up until that second line, after the first line has executed.). My original though was scope, local variables, stack issues, etc... But it's declared using new, which means it should be on heap, and I'm using a very similiar way of working with the pointers through all other parts of my project (And all seem to be behaving properly.). Also, it's only and always that second line; any sort of corruption should appear at random places right? That's when I thought about something mentioned in this page I was reading (A few months back when working with passing pointers for some recursive decent work elsewhere in the project):

"Pass by Pointer example:
[...]
The function cannot change the pointer itself since it gets a local copy of the pointer. However, the function can change the contents of memory, the variable, to which the pointer refers."

-- http://www.geekinter...n_details/16844

That's when I started wondering about some sort of subtle = or copy operator occuring. But I'm not sure how to breakpoint on a function call, I could "step into", but then I wind up stepping into nasty gory system code. Any thoughts? Thanks in advance!

Share this post


Link to post
Share on other sites
Advertisement
cSomeObject *Object = new cSomeObject();
Object = _GetObject();

Why you new an object, then override with _GetObject()?
What does _GetObject() do?

Also,
Object.SomeFunction()
How can you call a function via pointer using '.'?

Share this post


Link to post
Share on other sites
Hidden
Well, I originally had it without the new keyword, but then I was worried that without it, it might actually be declared on in stack space. So I switched it over to using the new keyword to be certain it was on heap; both ways yield the same result...

Share this post


Link to post
Well, I originally had it without the new keyword, but then I was worried that without it, it might actually be declared on in stack space. So I switched it over to using the new keyword to be certain it was on heap; both ways yield the same result...

Oh crud, didn't even notice it, yeah I mean object->

Problem with my posting is two fold: 1) It's 4am by me lol 2) It's no copy/pasted out of my existing code, it was merely meant to explain the layout of the object hierarchy.

Share this post


Link to post
Share on other sites
(really wish you could edit quick replys...) Essentially GetObject, is a function that contains a loop, that looks up peices and sets the pointers in cContainer to the result of the lookups. Increasing the cSomeSmallerObject instance of cSomeObject by one each time.

In other words:

cSomeObject *ReturnObject = new cSomeObject();
while loop should continue
lookup some text
if text is found: ReturnObject->SmallerObjects[ReturnObject->SmallerObjects.size()].Object = ResultLookupContainer;
else: error it wasn't found...
if loop should stop, then stop.

return ReturnObject;

Share this post


Link to post
Share on other sites
Hidden
[color=#000000]cSomeObject [color=#666600]*[color=#660066]Object[color=#000000] [color=#666600]=[color=#000000] [color=#000088]new[color=#000000] cSomeObject[color=#666600]();
[color=#000000] [color=#660066]Object[color=#000000] [color=#666600]=[color=#000000] _GetObject[color=#666600]()

Share this post


Link to post
I don't understand your explaination of the _GetObject() method.

The problem with those two lines are that you will leak the object you created with new when you call _GetObject()
What is _GetObject returning?
My guess is that it isn't returning a proper cSomeObject

It probably would be easier to spot the problem with some actual code then with your pseudocode representation of what you think you do.

Share this post


Link to post
Share on other sites
Ok after much needed sleep and then coffee tongue.png, I put a good portion of the actual code in a pastebin type of site here:

http://ideone.com/9W3q5

Hopefully that clears up any confussion. I still felt the need to remove some stuff out of it, because the code is going into a commercial product, as it is, there's still some stuff in there I'm not particularly crazy over still being in there, but without it I think it would just lead to more confusion; and it's definately not my intent to make things harder on the very people trying to help me. I really do appreciate the help! Let me know if there's anyting that's still confusing; as always, thanks in advance!

Share this post


Link to post
Share on other sites
Looked a bit at it, and I couldn't see any obvious problem :(

The weirdest part was that you seem to use map:s as if they are arrays, but I guess that should work, just a bit inefficient.
If you just want to map integers to objects, and they always are sequential 0...n, then you should use a vector.

Don't think that is the problem though, but thought I should mention it.

Share this post


Link to post
Share on other sites
Long post I know, sorry sad.png -- I broke it up though so you can read that parts that you want, or go back and finish reading the parts you may have skipped.

With regards to maps as arrays:
My intent is to use maps as arrays smile.png I do that deliberately, I kinda like having that random access. Granted yeah, no doubt, that portions of my code that don't need arrays could be written to use vectors, but then two things occur:

1) I wind up throwing another datatype into the mix (While on the surface may not be an issue, it has a widespread ripple effect on many other portions of code that may expect (And need), and use maps, or storage containers that use maps because those maps will be used in functions, so forth and so on...

2) I have this hang-up about coding myself into a corner, I guess I've been burnt too many times in past years, but I'd rather code for flexibility and power then speed and lock myself down. What I mean is, if down the line I decide to rewrite something that would benefit from the use of an array-style type, now I gotta go and rewrite it, and hope I don't have to rewrite any other rippling code. The thing about maps that I like about them being used (Asside from the previous benefits I mentioned) is essentially each element is a parameter, I can jump instantly to any parameter that is stored, I don't have to iterate through the object to get to it, so the potential performance is greater than the current actualized performance. Though, you're probably thinking right now (As I am), why would I need to jump parameters when parsing, wouldn't the normal behavior be looked at (Once they are parsed and stored into this array) in a linear fashion? And the answer, would be, probably yes, they would be. But then I go back to my hang-up on coding myself into what see as a potential corner. My philsophy and belief is: if, as I code, any corner-painting-code potentials, I come up to, is written to be as non-corner-painting-code as possible, theoryetically I will never have a problem going back and changing something. Which is pretty wishful thinking I know. Though the out of the pan and into the fire is certainly a possibility too, but this is all philosophical smile.png

Don't get me wrong I try not to waste performance, and I will be dedicating an entire phase towards performance, but with the power and speed of modern computers, it becomes less and less of an issue (Not to diminish the importance I mean...). The speed of my current code runs -blazingly- fast considering all the stuff going on in the background that it's doing; so, so far I'm pretty happy with the performance and as such, at the moment I'm able to have my cake and eat it too, so to speak (Besides, what good is the cake if you can't eat it? tongue.png ) All kidding aside, I do plan on a performance phase.


A slight aside:
A few days ago I ported the code to Linux to run with Valgrind, and I have an output file, but I'm not really completely sure the problem is caused by a memory leak yet. Not to mention, some of the log entries are a little cryptic. Either way, the porting kinda made a mess out of the code since things like enums can't be qualified by gcc; which to me is crazy-silly. WTH good is throwing stuff into a named enum if you can't qualify the name of the member by specifying the name of the enum it belongs to?! Now I gotta have the name of the enum prefixed to the enum members, just to ensure the member names are unique to other member names of other enums that may need to have similiar names; since essentially by removing the qualification, all enum members are implicilty put into sort of a global scope (In a sense.). This makes the point of naming enums completely and utterally moot, why not just have anonymous enums (Is that possible? I've never actually tried that), and to me, there's something bad about having anonymous anything. So I had to rename not only all members of (almost) all enums I had to make sure each reference to them throughout the code used those new names, it took close to three hours to do it by hand! I didn't trust find and replace on something on that kinda scale. Then I had spent hours trying to create a makefile and was constantly getting "Undefined reference" errors, then I tried the auto tools (autoconf, automake, etc.. to get me a proper makefile) What a mess that was! Then I eventually found CodeBlocks would allow me to compile without a premade makefile, it must've been generating one on the fly or something (After I added all the source and header files). Unfortunately the whole effort was for the most part a waste as I said the legendary Valgrind was only marginally useful. Then there was a little disaster with svn conflicts when trying to go back. It was an absolute mess. Not in real big hurry to port to Linux again until the project is much closer to release. Fortunately, I at least know some of the things I did wrong and will be keeping that in mind as I go forward...
/end_asside


Current thoughts:
Anyhow, yeah that's the same thing I keep coming up with -- not really any obvious problem... I've spent literally days working on this stupid bug. Really wish I knew where it was coming from. I tried loading it into OllyDbg, thinking I'll get not only integration of my source (Line numbers, and direct locating via double-clicking on the asm lines), but also the ability to not deal with the gory stl code (Giving me my desired Skip-Over-System-code feature.). Unfortunately, it seems there's a jmp to an address, and when I double click that address, Olly crashes. It may be because it's the 2.0 version which is in alpha 4 status; maybe I'll give it another shot tomorrow using a lower more stable version.

Ya know, it'd be so acceptable if the object wasn't being set from the first function call, I could say, well it went out of scope and maybe there was a pointer issue, blah blah blah, but the object persists, coming out of the function and into the next, and breaks when it goes into that second function. It makes like no sense. And it's not even like half-way or 3/4 of the way into the second function (At which point I'd be thinking: Ok, well maybe I messed it up by setting it to something somewhere in "here"), it's at the begining! Which makes me think stack. But it's on the heap and the object has been demonstrated to persist as it gets set and then continue to persist going into the function. I don't get it. There's only a couple of really "out there" cases I can think of.

Case 1: An = operator is being triggered by the pointer being copied via the thunk (Proper term here?) for the function (Though I think copys of pointers only occur if they are passed in as function parameters, not sure). Not sure what happends if a method of that pointer is called and that method operates on its on members. Probably the expected result, no major problem; because it seems like such a basic question. Further more, the this keyword implies that it's expected that people will write code that will call the method of an pointer object that operates on its members.

Case 2: I've read of a case where methods can commit suicide (Usually in smart pointers that deal with reference counters and supposedly in COM interfaces), however a number of caveats exist, one of them being that if delete is used on a class member, the member is deleted as it should be (The dtor is called, then the memory is freed), and the memory is freed; if delete is used on a class and that class is declared in a function, the delete will call the class's dtors (After the member dtors, of course) and, If its dtors issue a delete this, bad things happen because the delete keyword behaves as if its operating on heap memory when it's really in stack. (It was a really weird example, I may not be remembering it quite correctly.). This is significant not in the literal sense, but in the sense to demonstrate that there can be scenerios where one believes they are working with the heap when in fact they are working with the stack. I'm wondering if I'm in a similiar situation, though I don't think I am explicitly calling the destructors in any of my classes (Or sub-classes) potentially involved; though I'll have to double check this. I know for sure that I'm not issuing any "delete this;" lines, that much is for certain.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!