473,385 Members | 1,973 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

STL Map Scoping Issue

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;
}

Aug 12 '07 #1
11 2081
Hi!

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

sf*****@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.

To avoid this hassle try using boost::shared_ptr.

Frank
Aug 12 '07 #2
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
Aug 12 '07 #3
sf*****@gmail.com 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;
}
Aug 12 '07 #4
On Aug 12, 9:38 am, Frank Birbacher <bloodymir.c...@gmx.netwrote:
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

Aug 12 '07 #5
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 ^^^^^^^^^^^^^^^

Aug 12 '07 #6
Hi!

sf*****@gmail.com 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
Aug 12 '07 #7
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
Aug 12 '07 #8
Why don't I visit this site more often? You guys are great. Thank a
million.
Aug 12 '07 #9
Thank you! Very constructive comments that I will take to heart.

Aug 12 '07 #10
On Sun, 12 Aug 2007 09:38:40 +0200, Frank Birbacher wrote:
sf*****@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.
Must say I did not realise that until now. That is unbelievably ugly.

Using the following should be safe though:

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

--
Markus Schoder
Aug 15 '07 #11
Markus Schoder wrote:
:: On Sun, 12 Aug 2007 09:38:40 +0200, Frank Birbacher wrote:
::: sf*****@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.
::
:: Must say I did not realise that until now. That is unbelievably
:: ugly.

But that is also the way some hardware work(ed). Loading a pointer
into an address register might involve verifying access rights and/or
validity.

On a segmented system, like Windows 286 with 64 kB per segment,
deleting an entire segment might make the runtime release the segment
to to OS, which promptly removed the segment from the descriptor
table. Now, loading that pointer into a segment register would case a
missing segment trap.
This segment hardware is still present in 32 bit x86 processors,
though we don't use it much. The language rules are there to allow its
use, if anybody should want to!

::
:: Using the following should be safe though:
::
:: template<class Tvoid deleteAndZero(T *&p)
:: {
:: delete p;
:: p = NULL;
:: }
Yes.
Bo Persson
Aug 15 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: David Stockwell | last post by:
Hi, Another of my crazy questions. I'm just in the process of learning so bear with me if you can. I actually ran it.... with two test cases TEST CASE 1: Say I have the following defined:...
2
by: Robert M. Gary | last post by:
I'm curious what the ANSI C++ standard says about nested classes. I'm not able to find where in the ANSI C++ standard this is addressed. The issue is the accessibility of sibling nested classes....
4
by: Frederick Grim | last post by:
okay so the code in question looks like: namespace util { template<typename C> inline void mmapw(C *& ptr, size_t length, int prot, int flags, int fd, off_t offset) { if((ptr =...
2
by: macrom75 | last post by:
I have a script that I found online to do dynamic checking of passwords (for verifying that the re-typed password matches the original). This code works great in a basic HTML document, but when I...
1
by: Michael | last post by:
I am having a problem with scoping of parameters in my XSLT Stylesheet...here is the stylesheet (the xml document is irrelevant for the example) <?xml version="1.0" encoding="UTF-8"?>...
9
by: NevilleDNZ | last post by:
Can anyone explain why "begin B: 123" prints, but 456 doesn't? $ /usr/bin/python2.3 x1x2.py begin A: Pre B: 123 456 begin B: 123 Traceback (most recent call last): File "x1x2.py", line 13,...
3
by: morris.slutsky | last post by:
So every now and then I like to mess around with hobby projects - I often end up trying to write an OpenGL video game. My last attempt aborted due to the difficulty of automating game elements and...
17
by: Chad | last post by:
The following question stems from Static vs Dynamic scoping article in wikipedia. http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping Using this sites example, if I...
4
by: bob357 | last post by:
Hello everyone, I'm a novice programmer and am having trouble with a text-adventure game I am programming. There are two classes, Hero and Monster, that contain functions that I want to be able...
2
by: Joshua Kugler | last post by:
I am trying to use lamdba to generate some functions, and it is not working the way I'd expect. The code is below, followed by the results I'm getting. More comments below that. patterns = (...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.