Jump to content
  • Advertisement
Sign in to follow this  
Zouflain

[Resolved] (C++) deconstructor causing access violation in odd location

This topic is 3783 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

I have a class which has these members:
std::map<const char*,int> section_list;
std::vector<std::map<const char*,int>> section_key;
std::vector<char*> str_vals;
To summarize how they're used (which will explain an oddity the deconstructor), two strings can be used to return a single value. section_list maps a string to the location of a map in section_key. The maps in section_key map a second string to the location of a value in str_vals. To destroy this, I use:
for(unsigned int i=0;i<section_key.size();i++)
  section_key.at(i).clear();
section_list.clear();
section_key.clear();
str_vals.clear();
Which appears to clean up the used memory quite nicely, however once the program terminates, I receive an access violation. Even when I experimented by using a default destructor, the access violation still occurs. The "just in time" debugger points me to _Erase(_Root()); as the break point, though I don't know if that information is at all useful. I've little to no skill at debugging when it involves code I didn't personally write. [Edited by - Zouflain on February 8, 2008 5:26:02 AM]

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Zouflain
The "just in time" debugger points me to _Erase(_Root()); as the break point, though I don't know if that information is at all useful. I've little to no skill at debugging when it involves code I didn't personally write.

(Assuming you're using visual studio) If you look at the call-stack window when this happens, you should be able to step back through the stack until you get back to your own code.

[edit]
Also, adding "myMemberSTLContainer.clear();" into your destructor isn't actually needed. Your destructor will automatically call the destructors of all of your members, which in this case will free the memory used by your maps/vectors automatically.

Share this post


Link to post
Share on other sites
Thank you for the information. I wanted to be sure that the vector containing maps was completely cleared out, rather than form a memory leak by having maps without having been .clear()'ed. If this isn't necessary, that's relieving. I was certain this would lead to a memory leak.

As for what you said about debugging, however, I'm mostly drawing a blank. I am using Visual Studio, but usually I debug a program by studying my own work long enough to figure out where the potential buffer overflows are (or whatever the case may be) and correcting them that way. By call-stack I'll assume you mean the program's disassembly, and the specific line that generates the break point reads
00416679  mov         eax,dword ptr [eax]
I recognize it as assembly, but I've never studied it enough to understand this specific call.

As an aside, I should point out that I'm certain that this happens after all my code goes through, because I ran a bit of a test:
int main(){
various_operations()
printf("Other operations successful...\n");
system("PAUSE");
mycode();//including the destructor
printf("My operations successful...\n");
system("PAUSE");
return(0);
}
I get through the last system("PAUSE") without issue but right before the program completely terminates, the debugger alerts me to an access violation. I don't really get how this works; is windows trying to erase data that was already previously erased? And how can I prevent that?

The program is SDL based, by the way, and not platform dependent. I just happen to have compiled it in windows and Visual Studio.

Share this post


Link to post
Share on other sites
The char* and const char* template parameters alarm me.

How do you fill your map?


Also i often see global static maps causing problems. Are they global? If so try to encapsulate them somewhere to make sure they're getting destroyed earlier on.

Share this post


Link to post
Share on other sites
I see char*'s without any deletes, and that makes me worry. It's very likely you're leaking memory at the moment. Clearing a container of pointers only deletes the pointers themselves, but not what they point to. You still need to loop over the container and delete each pointer element, before clearing (or destructing).

If you're already deleting the pointers in those containers elsewhere, then disregard my post :)

Share this post


Link to post
Share on other sites
Any chance, you are using visual studio 6.0? I ran into a problem with std::map in 6.0's implementation once that caused deconstruction access violations after program completion as well. I spent some time banging my head on it before I decided to refactor around the map...either choosing a different structure for that job or putting pointers in it instead of objects. I really cant remember, but I do recall explicitly finding other people complaining about bugs in std::map for that release, which I attributed to my problem.

Sorry, not many more details, thats all I remember.

Share this post


Link to post
Share on other sites
I have a very limited ammount of globals, and these are things that really need to be the same throughout the program

--a boolean that must be true else the gameloop terminates (any point in program can kill game this way)
--The time (in ticks) at which the game started
--The time (in ticks) of the last frame
--The current number of ticks elapsed
--A member of this class (perhaps this is the issue?)
--A vector storing a set of objects, all derived from a generic base class with a few virtual functions (useful because I can use it to reference every active object which can in turn react to an event).

I did forget to destroy the vector, but as it's always in use until the game is over, I didn't see it as a priority (and, for good measure, I've just now .clear()'ed it in the cleanup. The global member of the class is because this is used to map control settings, and it is destroyed in the mycode() segment of the above test I ran without issue.

As for the char*... yeah, it's automatic for me to use cstrings rather than strings. Bad habit, which I'll fix, but first I need to find the problem here. Does that appear to be a part of the problem? It's undoubtedly possible.

Edit:

std::map<const char*,int>::iterator mapit;
mapit = section_list.begin();
for(;mapit!=section_list.end();++mapit){
delete mapit->first;
}
for(unsigned int i=0;i<section_key.size();i++){
mapit = section_key.at(i).begin();
for(;mapit!=section_key.at(i).end();++mapit)
delete mapit->first;
section_key.at(i).clear();
}
for(int j=0;j<str_vals.size();j++)
delete str_vals.at(j);
section_list.clear();
section_key.clear();
str_vals.clear();
Cleaner destructor. This one clears out those char*... rather sad that I completely forgot about them. Very poor practice, but that's why I'm doing what I'm doing; live and learn.

Edit (2):
A side note; I copied this into a function that wasn't declared as a deconstructor - no issue. Having just a blank deconstructor still generated the issue. I'm using Visual Studio 8.0.5 (a few trailing digits), if that's any help. I have gcc and MinGW but my linux is out of order anyway.

[Edited by - Zouflain on February 8, 2008 2:46:45 AM]

Share this post


Link to post
Share on other sites
You have a leak, invalid pointer or buffer overrun somewhere in you code. The callstack usually sits in the lower right window when you debug, and will show you the series of calls made. You can double-click in it to step to the point in the code, and that way backtrack to the point where it really crashes.

Share this post


Link to post
Share on other sites
Quote:
std::_Tree<std::_Tmap_traits<char const *,int,std::less<char const *>,std::allocator<std::pair<char const * const,int> >,0> >::begin()
From call stack, and this links me over to xtree. Even though it's something I really ought to know, I'm unfamiliar with the deconstructor for a map so it would be difficult to back trace any further. No call I make to begin() throws a violation (again, this is happening as the program closes, after all my code has executed and a system pause has interrupted things just to be sure). The only code after system("PAUSE") is return(0);

Share this post


Link to post
Share on other sites
Quote:
Original post by Zouflain

std::map<const char*,int>::iterator mapit;
mapit = section_list.begin();
for(;mapit!=section_list.end();++mapit){
delete mapit->first;
}
This much sends alarm bells ringing for me!
You really really must not use a char* as a map key.

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!