Link to home
Start Free TrialLog in
Avatar of Ajay Singh
Ajay Singh

asked on

0xC0000005 - Access violation- error while getting the vealue from a map

Hi,
 code is throwing the exception - 0xC0000005 - Access violation, while getting the values from a map.
below is the sample code for the reference


bool bFound = myMap.findvalue(strId, pData );

inside the findvalue()

it = mymap.find(strId);
pData  = it->second;
where it is iterator.


the exception occurs only in 64 bit machine. Please help.

Thanks,
Ajay
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

it = mymap.find(strId);
pData  = it->second;

Does the find actually find anything?  I suspect nothing is being found that matches and then attempting to use a nonsense value in the it->second is going to fail.
Also just what is it ?  (You say iterator but how is it declared?)
Could there be a truncation going on which would lead to an incorrect memory address?
you need to check against mymap.end()

it = mymap.find(strId);
pData = NULL;
if (it != mymap.end()
        pData  = it->second;
return (pData != NULL);

Open in new window


in the calling function you have to handle that the findvalue returns false and the pData was NULL.

Sara
fyi: std::map::find returns an iterator which points to the found node in the map tree. if the value was not found std::map::find returns a pointer to end() which points beyond the container boundaries. the access violation probably is due to it->second is an invalid pointer probably a null pointer.

Sara
To add to above comments, this issue should be data issue and not related to 64 bit or 32 bit as you have mentioned in your question that it is happening only on 64 bit.
If this is still not solved, can you please post the type of your MAP, myMap. What types does it contain? What is the key (first) and what is the value (second) in this map?
Also if you can do a add watch in debug mode on this variable, and see for the value that you are trying to find, if there is a entry in the map (first matching the find argument), and if it is present what is the corresponding value (second) value in the map. It would be good to see the screenshot of this map if even after the above recommendations this issue is not resolved.
Avatar of Ajay Singh
Ajay Singh

ASKER

Hi All,

Thanks for your valuable comments.
the exception comes when assigning the value i.e on below line of code.

pData  = it->second;

here is the map
myMap(String, pClass*)
here pClass is pointer to a class...
To repeat my first comment:
Does the find actually find anything?  I suspect nothing is being found that matches and then attempting to use a nonsense value in the it->second is going to fail.
Either your iterator it is pointing to myMap.end() or iterator it is valid but it->second (pClass*) is null.
Hence I asked you to check the while debugging by adding a watch to see what value exists in map and if the value you are finding exists, what is the second value for that entry in map.
To add watch while debugging:
Right click on the variable which you want to watch, and say either quick watch or add to watch.
Then before the find statement, for the value you are trying to find, expand the MyMap in the watch window and see if this value exists.
You will need to add below check before assigning the value
if(it!=mymap.end())
pData  = it->second;

Open in new window

@Karrtik
check is already in place.

@AndyAinscow
values are there in Map when inserted ..but it throws exception randomly . i beleive that somehow memory address is getting corrupted hence causing the error in  it->second.
Can you please post your updated code with checks added, how it looks after incorporating all the comments given so far?
Also is your program multithreaded and is this data (map or class pointer inside the map) shared across across these threads?
i beleive that somehow memory address is getting corrupted hence causing the error in  it->second.
that is not very likely. can you post the full code of the findvalue function and the definition of the mymap container?

additionally go to debug menu and choose Exceptions ... - Win32-Exceptions.

you will see a table of exceptions codes where ' c0000005 Access violation' is one of them.

check the checkbox right of ' c0000005 Access violation' (column Thrown).

if you do this and run your program again, the exception break will occur exactly at the statement where the error happened. 'access violation' means pointer error, so there is a pointer variable involved in the statement which is wrong or null.

Sara
@Sara: the exception doesn't occur while debugging. when the generated exe and dlls are deployed on server, it may occur for any key but always at line "it->second".

@Karrtik:
map is:
std:map<String, pClass*> mMyMap;
std:map<String, pClass*> iterator it;

code for fetching value:

pClass* = pClassptr;
it = mMyMap.find(strId);
if(it != mMyMap.end())
{
  pClassptr = it->second  // this is the line where exception is thrown.
}
Can you please answer this question?
 is your program multithreaded and is this data (map or class pointer inside the map) shared across across these threads?
Also, can you please share the code of your class pClass? (declaration)
Also in your code :

std:map<String, pClass*> iterator it;
This should be, I think
mMyMap::iterator it;
Hi Ajay,
If your program is not multi-threaded, however if map is in a DLL, which is accessed in a EXE, then there are access violation issues that can happen, this is because : (from: https://support.microsoft.com/en-us/kb/172396)
"Most classes in the Standard C++ Libraries use static data members directly or indirectly. Since these classes are generated through template instantiation, each executable image (usually with DLL or EXE file name extensions) will contain its own copy of the static data member for a given class. When a method of the class that requires the static data member is executed, it uses the static data member in the executable image in which the method code resides. Since the static data members in the executable images are not in sync, this action could result in an access violation or data may appear to be lost or corrupted. "

The solution I suggest is to export the template instantiation from DLL and import it to the EXE.
Please refer the detailed resolution below.
https://support.microsoft.com/en-us/kb/168958

Hope this helps.

Thanks,
Karrtik
it may occur for any key but always at line "it->second".
how could you know if it isn't debug code?

if you were right, it->second was on the right side of an assignment, hence it was read-only in the statement. the staement only could cause an access violation if the 'it' was invalid or corrupted. it is invalid if it equals myMap.end(). since you checked this case, the only other reasonable explanation was that the map and its iterators were corrupted for example by an other thread as assumed by Andy.

std:map<String, pClass*> iterator it;
This should be, I think
mMyMap::iterator it;
it should be

std::map<std::string, YourClass*>::iterator it;

Open in new window


you should post the real code and not type from memory since the code you posted has at least 3 mistakes:
- a class 'String' with a capital 'S' rarely would be used in normal (unmanaged) c++. 'String' is managed c++ string class and cannot used as a key for std::map as far as i know.
- 'pClass*' only would be ok, if 'pClass' is a class name. but it sounds like a variable name which could not be used as template type.
- the 'iterator' needs to be preceeded by '::' while you posted spaces instead.

Sara
Thanks for correcting Sara :-),
For a minute I missed and thought that MyMap is a typedef and not an actual variable.
hence I wrote:
mMyMap::iterator it;// This is incorrect

Open in new window


I have always use typedefs, and I felt the below is much easy to read and for any change later on:
typedef MyClass* MyClassPtr;// This is easy if we want to make it a shared ptr instead, like typedef shared_ptr<MyClass> MyClassPtr;
typedef std:map<string, MyClassPtr> MyMap;
typedef std:pair<string, MyClassPtr> MyPair;
MyMap mMyMap;
MyMap::iterator it;

Open in new window

Hi Sara,

 it is most probably the case where the  map and its iterators were corrupted.
so is there any thing that  can be check if iterator is valid or not ?

below is the code
std::map< string, MyClassPtr*> mMyMap;
std::map< string, MyClassPtr*>::iterator it;

here string is a key

but it throws access violation error when fetching the value.

MyClassPtr* pClassptr ;
it = mMyMap.find(strId);
if(it != mMyMap.end())
{
  pClassptr = it->second  // this is the line where exception is thrown.
}

so it looks like that iterator is corrupted.
so is there any way to check the iterator if it is valid or not?

Thanks,
Ajay
Hi Ajay,
if it is not equal to Map.end() means it is valid.
So after this statement it is corrupted means, either some other thread is simultaneously accessing it or if it accessed across DLL or exe it could be an issue for which I pasted an MS link in my previous comment.
So can you please confirm if your app is multi threaded and if this data is shared across the threads?
Also is this map created in a DLL and accessed in another DLL or exe?
Please clarify these questions for you us to help you.
Thanks,
karrtik
Hi Karrtik,
 the map is not shared across the dll. let me put in more direct way.

here MyClassPtr is a base class having a static map mMyMap and contains some virtual functions and two  non virtual method "register" <to fill the map> and "get" <to fetch the value from map>.

in the constructor of the child classes(lets say MyClassChild) of MyClassPtr , method "register" of base class MyClassPtr  is called to fill the map.
MyClassChild::MyClassChild()
{
  register("ChildId", this);
}

and the  value is fetched by the different class which is not child of MyClassPtr.
sample:
MyClassPtr* pClass;
pClass = MyClassPtr ::get("somevalidid");

all above operations are happeing within a single dll.
the code is working fine in development environment. but when it deploy in server it start to throw the exception, i managed to pin point the fault line of code by putting  message before and after the below line.

it->second;
and it never log the message after this line when access viollation occurs.

P:S: the application is not multithreaded.
ASKER CERTIFIED SOLUTION
Avatar of Karrtik Iyer
Karrtik Iyer
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
In development environment have your tried with release build? Or have you tried in development env only with debug version of your DLL?
the code is working fine in development environment. but when it deploy in server it start to throw the exception
that is a hint that some variable (or a pointer) is not initialized. in debug mode all variables are initialized with zero values. in release mode a variable not initialized may contain any arbitrary value.

MyClassPtr is a base class having a static map mMyMap
a static member of type std::map can arise some problems. for example if you have other classes with static members as well, those members may be initialized prior to the std::map. if initialization code would try to access the std::map while it is not yet initialized, the behavior is undefined and the map could be corrupted. the only sure way out from this is to put all initializations of static members into one cpp file and do the static initialization in correct order. but this way is not recommended.

instead you may do the following:

don't define the member variable in the class but define it as static variablein a static function of the class:

typedef std::map<std::string, MyData *> MyMap;
class MyClass
{
public:
      static MyMap& GetMap() { static MyMap theMap; return theMap; }
      ...
};

Open in new window


whenever you need to access the map, you would do like

// fill the map
MyMap & myMap = MyClass::GetMap();
for (int n = 0; n < myPtrs.size(); ++n)
{
      std::string text = LoadText[myPtrs[n]->m_strID);
      myMap[text] = myPtrs[n];
}
...
// search in the map
MyMap::iterator f;
if ((f = MyClass::GetMap().find(searchstring)) != MyClass::GetMap().end())
{
       retPtr = f->second;
}

Open in new window


doing so has many advantages. one is that the static initialization happens when the first call to GetMap occurs. all other static members are correctly instantiated at this time. another point is that you easily could put the class into a dll and export it. since it no more has static members it could be done without wrapper functions. in your case, the map rarely wouldn't get corrupted. however, if some pointer issue or initialization issue still exists, the problem might arise for another container.

Sara
Have you looked at a tool such as BoundsChecker which examines memory used by an app during its execution?  Tools like that are designed to spot errors such as the one you are experiencing.
hi sara,
thanks for your long detailed comment..but this approach can't be implemented as the map stores the non static instance of class.

Thanks,
Ajay
Hi Ajay, how about my suggestion in my last comment of having a separate factory class as singleton? Have you gone through that approach?
Also have you looked at what I suggested - twice?

One can keep stumbling around in the dark until one eventually finds the problem or one can try to switch a light on.  Attempting to find what is corrupting memory is a nightmare task because it usually happens somewhere else entirely than where the problem surfaces.
can't be implemented as the map stores the non static instance of class.

that is fine. a static container of a class pretty well could store all non-static elements of the same class:

//forward declaration
class MyClass;
typedef std::map<std::string, MyClass *> MyMap;
class MyClass
{
      std::string myname;  // assume all objects have a unique name
public:
      static MyMap& GetMap() { static MyMap theMap; return theMap; }
      MyClass(const std::string & name) : myname(name) { GetMap()[name] = this; }
    ~MyClass() { MyMap::iterator f = GetMap().find(myname); if (f != GetMap().end()) GetMap().erase(f); }
      MyClass * FindMyClassByName(const std::string & name) 
       { MyMap::iterator f = GetMap().find(name); return (f != GetMap().end()) ? *f : NULL; } 
};

Open in new window

Hi All,

the issue got resolved as i moved out the definition of map from the base class.

Thanks all for your kind contributions

Thanks,
Ajay
>>the issue got resolved as i moved out the definition of map from the base class.

Unless you know what was causing the error you can not with certainty say it is cured.

Absence of evidence is not evidence of absence.
Ajay, if you see my comment that was what I had recommended to keep the interface and factory separate. (https://www.experts-exchange.com/questions/28871019/0xC0000005-Access-violation-error-while-getting-the-vealue-from-a-map.html?anchorAnswerId=41319087#a41319087)
But I cannot agree more with Andy's comments.