• Advertisement
Sign in to follow this  

constructing on the stack

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

Is my constructor for A correct?
class A{
public:
std::map<void*, bool> mymap;
void Task();
A();
};

A::A()
:mymap()
{}

void A::Task() {
for(std::map<void*,bool>::iterator i=mymap.begin(); i != mymap.end(); ++i)
{
//this crashes before the body of the for loop.  Haven't added any items yet.
}
Unhandled exception at 0x10e9e3b6 (my.dll) in c4.exe: 0xC0000005: Access violation reading location 0x00000018. edit: fixed all the usual inconsistencies when isolating the problem for posting.

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by thedustbustr
Is my constructor for A correct?


Yes, but the empty mymap initialiser is redundant as the default constructor will be called for the std::map<> anyway.


A::A()
{}


has the same effect (as indeed, in this case, does providing no constructor at all for A and accepting the default instead).

I can't see anything in the code you have posted that would cause a crash, since an empty map's begin() will return an iterator equal to the one returned by end():


#include <iostream>
#include <map>

std::map<void*,bool> m;

int main()
{
if(m.begin()==m.end()) std::cout << "proof\n";
}


Therefore the body of the for loop you posted will never execute unless something has been added to the map prior to your call to A::Task().

What does your question have to do with constructing on the stack?

[EDIT] One thing that has occurred to me is that using a pointer type as the key type for a std::map<> is a potentially worrying thing to do, but I think you need to post some more code.

[Edited by - EasilyConfused on October 30, 2007 3:18:26 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by thedustbustr
my code crashes inside of begin(). i guess the problem is elsewhere.


Given that std::map<>::begin() definatley works, and this begin() appears to be the first thing in the method that actually references the A object you are calling Task() on (by calling a method of one of A's members), my first thought would be that you are calling Task() on something like a NULL pointer, or a previously deleted instance of A or something like that.

I'd look at the code calling Task() rather than inside any of A's methods.

Share this post


Link to post
Share on other sites
problem was that due to dumb design constraints I'm forced to make it as a singleton, and I was never creating the initial instance. Which I should have realized from the very low address of the violation. As you pointed out about A being null.

Share this post


Link to post
Share on other sites
Quote:
Original post by thedustbustr
problem was that due to dumb design constraints I'm forced to make it as a singleton, and I was never creating the initial instance.

You're never forced to make anything a singleton. Redesign. Nine times out of ten, the issue is a failure for the design to unambiguously account for ownership of the object in question.

Share this post


Link to post
Share on other sites
Error messages often contain a lot of information. Just because it's a common error, don't disregard the details of an unhandled-exception message:
Quote:
Original post by thedustbustr
Unhandled exception at 0x10e9e3b6 (my.dll) in c4.exe: 0xC0000005: Access violation reading location 0x00000018.

There is a plethora of useful information here.

1. We have an access violation. Somebody attempted to read, write or execute memory that wasn't available to them.

2. The fault occurred when reading memory. It's no coincidence that begin is essentially an accessor function for the vector's array.

3. The error occurred when executing 0x10E9E3B6. This immediately tells me that the error occurred in DLL code. The rule-of-thumb is that 0x004xxxxx is the main module (exe) and anything higher is a DLL. Nowadays it's not so important to memorise these facts though, as Windows kindly tells you the name of the offending module.

4. The page-fault occurred when accessing 0x00000018. Small values like this are indicators of an attempt to dereference a null pointer. In this case, begin was implicitly passed NULL for this and the command to return this->_myPtr (or whatever) resulted in an attempt to dereference *(0x00000000 + 0x18).

Similar analyses on the offending page can be applied to many other addresses. Generally, though not always, the following addresses correspond to predictable memory locations:

0x0012xxxx - Main thread stack variable
0x001xxxxx - A secondary thread stack variable
0x004xxxxx - Initialised constant data or resource
0x0xxxxxxx - A heap belonging to the main module
0xxxxxxxxx - A heap belonging to a DLL

This is all deducible without even touching the debugger. From your first post alone, we can be sure that the error occurs either in mymap.begin or mymap.end, and that mymap == NULL at that time. And this could only have happened if mymap failed to have been initialised, which could only have been a result of a rogue static modifier [smile].

Admiral

Share this post


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

  • Advertisement