Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > STL Map Scoping Issue

Reply
Thread Tools

STL Map Scoping Issue

 
 
sfncook@gmail.com
Guest
Posts: n/a
 
      08-12-2007
I have some code that needs to declare an STL Map in the static scope,
insert values into the map in the function of one class and access the
values in the functions of other classes. This seems like a pretty
straight forward request, but when I implement it I get either garbage
data when I try to access it or I get an Access Violation runtime
error (depending on the state of my code while I try to figure out how
to get this rediculously simple idea to work). What the heck?! What
am I doing wrong? Here is some sample code that gives an Access
Violation:

typedef struct _ShipType {
int a;
int b;
int c;
} ShipType;

static std::map<int, ShipType *> shipTypeMap;

void GameLoader::LoadGame()
{
shipTypeMap[0] = new ShipType();
shipTypeMap[0]->a = 1;
shipTypeMap[0]->b = 2;
shipTypeMap[0]->c = 3;
}

int main(int argc, char* argv[])
{
printf("Callback function test.\n");

GameLoader * gl = new GameLoader();

gl->LoadGame();

std::cout<<shipTypeMap[0]->a<<std::endl;//<-----0xC000000005 Access
Violation here

delete shipTypeMap[0];

getchar();

return 0;
}

 
Reply With Quote
 
 
 
 
Frank Birbacher
Guest
Posts: n/a
 
      08-12-2007
Hi!

So far I have no idea what is causing the AV.

schrieb:
> delete shipTypeMap[0];


At least you have undefined behaviour here: deleted pointers are
invalid. invalid pointers may not be read or copied, but only be
assigned to or destructed (when going out of scope). But elements of a
map must be copyable. So you should first remove the pointer from the
map (store it in a local variable) and then delete the object it points to.

To avoid this hassle try using boost::shared_ptr.

Frank
 
Reply With Quote
 
 
 
 
Gianni Mariani
Guest
Posts: n/a
 
      08-12-2007
wrote:
> I have some code that needs to declare an STL Map in the static scope,
> insert values into the map in the function of one class and access the
> values in the functions of other classes. This seems like a pretty
> straight forward request, but when I implement it I get either garbage
> data when I try to access it or I get an Access Violation runtime
> error (depending on the state of my code while I try to figure out how
> to get this rediculously simple idea to work). What the heck?! What
> am I doing wrong? Here is some sample code that gives an Access
> Violation:
>
> typedef struct _ShipType {
> int a;
> int b;
> int c;
> } ShipType;
>
> static std::map<int, ShipType *> shipTypeMap;

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I can only think that you're seeing this in more than one compilation unit.
>
> void GameLoader::LoadGame()
> {
> shipTypeMap[0] = new ShipType();
> shipTypeMap[0]->a = 1;
> shipTypeMap[0]->b = 2;
> shipTypeMap[0]->c = 3;
> }
>
> int main(int argc, char* argv[])
> {
> printf("Callback function test.\n");
>
> GameLoader * gl = new GameLoader();
>
> gl->LoadGame();
>
> std::cout<<shipTypeMap[0]->a<<std::endl;//<-----0xC000000005 Access
> Violation here
>
> delete shipTypeMap[0];
>
> getchar();
>
> return 0;
> }
>


The code below compiles and runs as expected.


#include <map>
#include <iostream>

typedef struct _ShipType {
int a;
int b;
int c;
} ShipType;

static std::map<int, ShipType *> shipTypeMap;

struct GameLoader
{
void LoadGame();
};

void GameLoader::LoadGame()
{
shipTypeMap[0] = new ShipType();
shipTypeMap[0]->a = 1;
shipTypeMap[0]->b = 2;
shipTypeMap[0]->c = 3;
}

int main(int argc, char* argv[])
{
printf("Callback function test.\n");

GameLoader * gl = new GameLoader();

gl->LoadGame();

std::cout<<shipTypeMap[0]->a<<std::endl;

delete shipTypeMap[0];

getchar();

return 0;
}
 
Reply With Quote
 
Frank Birbacher
Guest
Posts: n/a
 
      08-12-2007
Hi!

I ran the following code. It doesn't crash on my system. I can't think
of a reason why it should crash at the cout line. Anyway, I don't
understand why you need static storage.

#include <iostream>
#include <ostream>
#include <map>
#include <stdio.h>

struct GameLoader
{
void LoadGame();
};

typedef struct _ShipType {
int a;
int b;
int c;
} ShipType;

static std::map<int, ShipType *> shipTypeMap;

void GameLoader::LoadGame()
{
shipTypeMap[0] = new ShipType();
shipTypeMap[0]->a = 1;
shipTypeMap[0]->b = 2;
shipTypeMap[0]->c = 3;
}

int main(int argc, char* argv[])
{
printf("Callback function test.\n");

GameLoader * gl = new GameLoader();

gl->LoadGame();

std::cout<<shipTypeMap[0]->a<<std::endl;//<-----0xC000000005
AccessViolation here

delete shipTypeMap[0];

getchar();

return 0;
}

Frank
 
Reply With Quote
 
Markus Schoder
Guest
Posts: n/a
 
      08-12-2007
On Sun, 12 Aug 2007 09:38:40 +0200, Frank Birbacher wrote:
> schrieb:
>> delete shipTypeMap[0];

>
> At least you have undefined behaviour here: deleted pointers are
> invalid. invalid pointers may not be read or copied, but only be
> assigned to or destructed (when going out of scope). But elements of a
> map must be copyable. So you should first remove the pointer from the
> map (store it in a local variable) and then delete the object it points
> to.


Must say I did not realise that until now. That is unbelievably ugly.

Using the following should be safe though:

template<class T> void deleteAndZero(T *&p)
{
delete p;
p = NULL;
}

--
Markus Schoder
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-12-2007
On Aug 12, 9:38 am, Frank Birbacher <bloodymir.c...@gmx.net> wrote:

> So far I have no idea what is causing the AV.


> sfnc...@gmail.com schrieb:


> > delete shipTypeMap[0];


> At least you have undefined behaviour here: deleted pointers are
> invalid. invalid pointers may not be read or copied, but only be
> assigned to or destructed (when going out of scope). But elements of a
> map must be copyable. So you should first remove the pointer from the
> map (store it in a local variable) and then delete the object it points to.


That's in theory. In practice, of course, there's no problem on
any real architecture; no implementation of std::map will read
or copy the pointer unless you actually try to access it.

> To avoid this hassle try using boost::shared_ptr.


Sounds like added complexity for no gain.

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
sfncook@gmail.com
Guest
Posts: n/a
 
      08-12-2007
Wow! You guys are great! Thanks for the responses so far. However, I
forgot to mention one factor that must make the difference: The code
is broken up into different files. I copied the code you had and ran
it fine from a single file as well. However when I divide the code
into different files (as is below) then I get the AV. Thanks a
million for the help so far. Please teach me oh wise sages.

********* typedefs.h *****************
#include "stdlib.h"
#include <map>
#include <vector>

typedef struct _ShipType {
int a;
int b;
int c;
} ShipType;

static std::map<int, ShipType *> shipTypeMap;


************** GameLoader.h ********************
#pragma warning (disable : 4786) //This is a fix for a Microsoft
acknowledged bug.

#include "typedefs.h"

class GameLoader
{
private:
public:
GameLoader(){};
virtual ~GameLoader(){};
void LoadGame();
};

************ GameLoader.cpp *********************
#include "GameLoader.h"

void GameLoader::LoadGame()
{
shipTypeMap[0] = new ShipType();
shipTypeMap[0]->a = 1;
shipTypeMap[0]->b = 2;
shipTypeMap[0]->c = 3;
}


****************** MainFile.cpp *********************
#include "GameLoader.h"

#include <stdlib.h>
#include <iostream>
#include <map>

int main(int argc, char* argv[])
{
printf("Callback function test.\n");

GameLoader * gl = new GameLoader();

gl->LoadGame();

std::cout<<shipTypeMap[0]->a<<std::endl;

delete shipTypeMap[0];

getchar();

return 0;
}

^^^^^^^^^ FIN ^^^^^^^^^^^^^^^

 
Reply With Quote
 
Frank Birbacher
Guest
Posts: n/a
 
      08-12-2007
Hi!

schrieb:
> Wow! You guys are great! Thanks for the responses so far. However, I
> forgot to mention one factor that must make the difference: The code
> is broken up into different files.


Indeed that is the difference, as Gianni already pointed out.

> ********* typedefs.h *****************
> #include "stdlib.h"
> #include <map>
> #include <vector>
>
> typedef struct _ShipType {
> int a;
> int b;
> int c;
> } ShipType;
>
> static std::map<int, ShipType *> shipTypeMap;


This definition of shipTypeMap includes "static". That makes shipTypeMap
appear mutiple times: once for each translation unit (= cpp file). So
your initialisation code initialises one instance while the other code
accesses the uninitialised one => oops. You need to do the following:

typedefs.h:
extern std::map<int, ShipType*> shipTypeMap;

somewhere.cpp:
std::map<int, ShipType*> shipTypeMap;

This makes one global instance of shipTypeMap which is then access from
all code.

HTH,
Frank
 
Reply With Quote
 
Frank Birbacher
Guest
Posts: n/a
 
      08-12-2007
Hi!

James Kanze schrieb:
> That's in theory. In practice, of course, there's no problem on
> any real architecture; no implementation of std::map will read
> or copy the pointer unless you actually try to access it.


Yes, no problem in practise.

>> To avoid this hassle try using boost::shared_ptr.

>
> Sounds like added complexity for no gain.


Sounds like added memory security for little effort as well. Even if it
is of little help with uninitialised pointers it is of great help for
managing memory (less leaks) and exception safety.

Frank
 
Reply With Quote
 
sfncook@gmail.com
Guest
Posts: n/a
 
      08-12-2007
Why don't I visit this site more often? You guys are great. Thank a
million.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
STL map+vector compilation failure issue boltar2003@yahoo.co.uk C++ 3 04-30-2009 01:46 PM
STL map or hash map using struct as data and find it kl C++ 7 01-01-2008 11:05 AM
STL map with key as a structure compare function issue addy.varma@gmail.com C++ 2 05-04-2006 12:33 PM
a stl map which use stl pair as the key Allerdyce.John@gmail.com C++ 2 02-22-2006 07:25 AM
STL: Map of maps possible, but no multi-map of maps? Workarounds? Marcus C++ 2 12-09-2005 06:34 AM



Advertisments