Hi, I'm trying to keep MFC out of this project and so I'm using the
stl std::map on the heap. I was originally using a char * as the key,
but I ran into the "duh, obvious -- it's comparing pointers" issue,
and switched to the CString (<atlstr.h> version, NOT the CLR version)
use. I thought this would solve the pointer issue since the operators
for CString are overridden.

Now, I declare the map as:

std::map<CString, byte*>* g_VarMap; //byte is typdef'd unsigned
char. also on the heap.

Now, I add strings to the map and this works entirely as expected.
However, later on, I try to do a find() to grab the value. Now,
digging into the guts, the find() is doing an == to detect if the
objects are the same. CString has overrided this operator so that it
compares the guts of the strings, not the pointers.

I still get find failing. Here's an example of a little dummy test.

Now, as you can see here, my map has the strings in it and pointers to
memory locations.
- g_VarMap [5](("AA",0x003a9e0b ""),("BB",0x003a9e1b ""),("XX",
0x003a9c95 ""),("YAR",0x003a9c96 ""),("YY",0x003a9c94 ""))

find returned (<Bad Ptr>,0xcdcdcdcd <Bad Ptr>)

when I do a find on YAR.

The code is a bit long to put here, but I'm sure this is something you
know the answer to.

Any ideas? To me, the == operator should return that there is a
match.

Re: Stl map and CString trouble by Duane

Duane
Fri Oct 03 09:26:07 CDT 2008

"Scoots" <linkingfire@msn.com> wrote in message
news:3bb46a6c-c861-4419-a425-74c5aaf9d37b@h60g2000hsg.googlegroups.com...
> Hi, I'm trying to keep MFC out of this project and so I'm using the
> stl std::map on the heap. I was originally using a char * as the key,
> but I ran into the "duh, obvious -- it's comparing pointers" issue,
> and switched to the CString (<atlstr.h> version, NOT the CLR version)
> use. I thought this would solve the pointer issue since the operators
> for CString are overridden.
>
> Now, I declare the map as:
>
> std::map<CString, byte*>* g_VarMap; //byte is typdef'd unsigned
> char. also on the heap.
>
> Now, I add strings to the map and this works entirely as expected.
> However, later on, I try to do a find() to grab the value. Now,
> digging into the guts, the find() is doing an == to detect if the
> objects are the same. CString has overrided this operator so that it
> compares the guts of the strings, not the pointers.
>
> I still get find failing. Here's an example of a little dummy test.
>
> Now, as you can see here, my map has the strings in it and pointers to
> memory locations.
> - g_VarMap [5](("AA",0x003a9e0b ""),("BB",0x003a9e1b ""),("XX",
> 0x003a9c95 ""),("YAR",0x003a9c96 ""),("YY",0x003a9c94 ""))
>
> find returned (<Bad Ptr>,0xcdcdcdcd <Bad Ptr>)
>
> when I do a find on YAR.
>
> The code is a bit long to put here, but I'm sure this is something you
> know the answer to.
>
> Any ideas? To me, the == operator should return that there is a
> match.


Why do you need pointers for the map and the bytes?
Anyway, how do you assign to the map?
How do you create the byte*?

What if you use:
std::map<std::string, std::string> g_VarMap;

and do
g_VarMap [5](("AA",0x003a9e0b ""),("BB",0x003a9e1b ""),("XX",
> 0x003a9c95 ""),("YAR",0x003a9c96 ""),("YY",0x003a9c94 ""))

g_VarMap["AA"] = "0x003a9e0b";
g_VarMap["BB"] = "0x003a9e1b ";
g_VarMap["XX"] = "0x003a9c95 ";
g_VarMap["YAR"] = "0x003a9c96 ";
g_VarMap["YY"] = "0x003a9c94 ";

then:

std::map<std::string,std::string>::iterator it = g_VarMap.find("YAR");
if(it != g_VarMap.end()) {
//do something with it.second.
}


Re: Stl map and CString trouble by Duane

Duane
Fri Oct 03 09:30:14 CDT 2008

> and do
> g_VarMap [5](("AA",0x003a9e0b ""),("BB",0x003a9e1b ""),("XX",
>> 0x003a9c95 ""),("YAR",0x003a9c96 ""),("YY",0x003a9c94 ""))

Sorry, I dropped the copy/paste here.

Re: Stl map and CString trouble by Scoots

Scoots
Fri Oct 03 10:20:00 CDT 2008

On Oct 3, 10:26=A0am, "Duane Hebert" <s...@flarn.com> wrote:
" Why do you need pointers for the map and the bytes?"
the map is on the heap, so I need a pointer to it. The bytes are also
an allocated chunk on the heap, and so I need the addresses for an
application specific task.

> Anyway, how do you assign to the map?
It's over several hundred to thousand lines of parsing a file, but it
boils down to:

int MapVar(string p_pszName, char* p_pszType)
{

//If bool, update boolspace vars.
if (0 =3D=3D strcmp("BOOL",p_pszType))
{
if (g_pbCurrentBoolSpace + sizeof(bool) >
(bool*)g_piCurrentIntSpace) //this also handily catches if it's
already maxed!
{
Monitor(MON_ALWAYS, "MapVar",
"Fatal Error -- bool var space overlapped with int space. %s",
"Forcing Preprocessor Run.");
return 0;
}
(*g_VarMap)[p_pszName] =3D (byte*)(g_pbCurrentBoolSpace);
g_pbCurrentBoolSpace +=3D sizeof(bool);
}

//If int, update int vars.
if (0 =3D=3D strcmp("INT", p_pszType))
{
if (g_piCurrentIntSpace + sizeof(int) >
(int*)g_pfCurrentFloatSpace) //this also handily catches if it's
already maxed!
{
Monitor(MON_ALWAYS, "MapVar",
"Fatal Error -- int var space overlapped with float space. %s",
"Forcing Preprocessor Run.");
return 0;
}
(*g_VarMap)[p_pszName] =3D (byte*)(g_piCurrentIntSpace);
g_piCurrentIntSpace +=3D sizeof(int);
}

//If float, update float vars.
if (0 =3D=3D strcmp("FLOAT", p_pszType))
{
if (g_pfCurrentFloatSpace + sizeof(float) > (float*)g_VarSpaceMax) //
this also handily catches if it's already maxed!
{
Monitor(MON_ALWAYS, "MapVar",
"Fatal Error -- float var space overflowed with var space. %s",
"Forcing Preprocessor Run.");
return 0;
}
(*g_VarMap)[p_pszName] =3D (byte*)(g_pfCurrentFloatSpace);
g_pfCurrentFloatSpace +=3D sizeof(float);
}
return 1;
}

> How do you create the byte*?
typdef. it's an unsigned char.

>
> What if you use:
> std::map<std::string, std::string> g_VarMap;
>
> and do
> g_VarMap [5](("AA",0x003a9e0b ""),("BB",0x003a9e1b ""),("XX",
>
> > 0x003a9c95 ""),("YAR",0x003a9c96 ""),("YY",0x003a9c94 ""))
>
> g_VarMap["AA"] =3D "0x003a9e0b";
> g_VarMap["BB"] =3D "0x003a9e1b ";
> g_VarMap["XX"] =3D "0x003a9c95 ";
> g_VarMap["YAR"] =3D "0x003a9c96 ";
> g_VarMap["YY"] =3D "0x003a9c94 ";
>
> then:
>
> std::map<std::string,std::string>::iterator it =3D g_VarMap.find("YAR");
> if(it !=3D g_VarMap.end()) {
> =A0 =A0 //do something with it.second.
>
I get the same result, in the same place.
std::string szName =3D pszVar;
toUpper(szName);
iter =3D g_VarMap->find(szName); <<returns garbage.


I prefer to use CStrings if I can, for the utility and the unicode
support. That said... I still have the problem. As of right now, the
memory locations aren't critical... I haven't made it that far. I'm
just trying to get the map to cooperate. If it compares a pointer,
this obviously fails. If it compares values this should never be
failing. And CString has the =3D=3D overloaded, which I believe is what
the find() uses (insert and [] use <, but I think the find() uses =3D=3D).

Re: Stl map and CString trouble by Scoots

Scoots
Fri Oct 03 10:24:02 CDT 2008

" Why do you need pointers for the map and the bytes?"
the map is on the heap, so I need a pointer to it. The bytes are
also
an allocated chunk on the heap, and so I need the addresses for an
application specific task.


> Anyway, how do you assign to the map?


It's over several hundred to thousand lines of parsing a file, but it
boils down to:

int MapVar(string p_pszName, char* p_pszType)
{
//If bool, update boolspace vars.
if (0 == strcmp("BOOL",p_pszType))
{
if (g_pbCurrentBoolSpace + sizeof(bool) >
(bool*)g_piCurrentIntSpace) //this also handily catches if it's
already maxed!
{
//snip
return 0;
}
(*g_VarMap)[p_pszName] = (byte*)
(g_pbCurrentBoolSpace);
g_pbCurrentBoolSpace += sizeof(bool);
}


//If int, update int vars.
if (0 == strcmp("INT", p_pszType))
{
if (g_piCurrentIntSpace + sizeof(int) >
(int*)g_pfCurrentFloatSpace) //this also handily catches if it's
already maxed!
{
//snip
return 0;
}
(*g_VarMap)[p_pszName] = (byte*)
(g_piCurrentIntSpace);
g_piCurrentIntSpace += sizeof(int);
}


//If float, update float vars.
if (0 == strcmp("FLOAT", p_pszType))
{
if (g_pfCurrentFloatSpace + sizeof(float) >
(float*)g_VarSpaceMax) //
this also handily catches if it's already maxed!
{
//snip
return 0;
}
(*g_VarMap)[p_pszName] = (byte*)
(g_pfCurrentFloatSpace);
g_pfCurrentFloatSpace += sizeof(float);
}
return 1;



}
> How do you create the byte*?


typdef. it's an unsigned char.



- Hide quoted text -
- Show quoted text -

> What if you use:
> std::map<std::string, std::string> g_VarMap;


> and do
> g_VarMap [5](("AA",0x003a9e0b ""),("BB",0x003a9e1b ""),("XX",


> > 0x003a9c95 ""),("YAR",0x003a9c96 ""),("YY",0x003a9c94 ""))


> g_VarMap["AA"] = "0x003a9e0b";
> g_VarMap["BB"] = "0x003a9e1b ";
> g_VarMap["XX"] = "0x003a9c95 ";
> g_VarMap["YAR"] = "0x003a9c96 ";
> g_VarMap["YY"] = "0x003a9c94 ";


> then:


> std::map<std::string,std::string>::iterator it = g_VarMap.find("YAR");
> if(it != g_VarMap.end()) {
> //do something with it.second.



I get the same result, in the same place.
std::string szName = pszVar;
toUpper(szName);
iter = g_VarMap->find(szName); <<returns garbage.

I prefer to use CStrings if I can, for the utility and the unicode
support. That said... I still have the problem. As of right now,
the
memory locations aren't critical... I haven't made it that far. I'm
just trying to get the map to cooperate. If it compares a pointer,
this obviously fails. If it compares values this should never be
failing. And CString has the == overloaded, which I believe is what
the find() uses (insert and [] use <, but I think the find() uses
==).



Re: Stl map and CString trouble by Duane

Duane
Fri Oct 03 10:31:52 CDT 2008

"Scoots" <linkingfire@msn.com> wrote in message
news:8cff90e0-bcda-4df0-8a2a-17e108b0bcf4@w32g2000hsf.googlegroups.com...

>I get the same result, in the same place.
>std::string szName = pszVar;
>toUpper(szName);
>iter = g_VarMap->find(szName); <<returns garbage.

Is it returning garbage or is it returning end()?
Before using the results of find() you need to
compare it to g_VarMap.end().

>I prefer to use CStrings if I can, for the utility and the unicode
>support. That said... I still have the problem. As of right now, the
>memory locations aren't critical... I haven't made it that far. I'm
>just trying to get the map to cooperate. If it compares a pointer,
>this obviously fails. If it compares values this should never be
>failing. And CString has the == overloaded, which I believe is what
>the find() uses (insert and [] use <, but I think the find() uses ==).

I don't think the problem is with CString though I don't use that.
I think the problem is more likely with the pointers. Like why
is your map a pointer and why is your byte a pointer? Do you
allocate space for them?

Your aggregate looking init that you show doesn't compile for me.
I would expect to have to use boost::assign or something to do that.

That's why I asked what would happen if you use a map created on
the stack.

Are you sure that it's not a case of find failing and you not
checking it properly? If so, the problem may not be that
the map has garbage but that it isn't storing the value as
you think? Do you see what I mean? If std::find() returns
map::end() then it's not in the map.


Re: Stl map and CString trouble by Scoots

Scoots
Fri Oct 03 10:44:29 CDT 2008

> Is it returning garbage or is it returning end()?
> Before using the results of find() you need to
> compare it to g_VarMap.end().
it returns a bad ptr according to Visual Studio. This is failing to
find a value that I know is in there (on the line of the find, I've
printed out the map before and the value is there (lexographically).

> I don't think the problem is with CString though I don't use that.
> I think the problem is more likely with the pointers. =A0Like why
> is your map a pointer and why is your byte a pointer? =A0Do you
> allocate space for them?

I've answered you in both of my posts on this. My map is a pointer
because it is on the heap.
g_VarMap =3D new std::map<string, byte *>();

and I want it on the heap. That was very intentional.

my byte is an unsigned byte. I have a pointer because I'm storing a
location in a chuck of them defined as follows:
g_VarSpace =3D new byte[iVarSpaceSize]; //Allocate the variable space.

by now you have probably guessed that the "floats" etc that I am
storing are special data types relative to this application which is
acting as a preprocessor and interpretter.

> Your aggregate looking init that you show doesn't compile for me.
> I would expect to have to use boost::assign or something to do that.

My what?


> That's why I asked what would happen if you use a map created on
> the stack.

Okay, I missed that that was what you wanted me to do. When I ran it,
I did switch to strings but it was still on the heap.



> Are you sure that it's not a case of find failing and you not
> checking it properly? =A0If so, the problem may not be that
> the map has garbage but that it isn't storing the value as
> you think? =A0Do you see what I mean? =A0If std::find() returns
> map::end() then it's not in the map.

I think regardless of which it is (and yes, I will check for end), it
is failing to find the string in there, in this manufactured test case
when I'm searching for something I know is in there, and it is when I
print it out just before the find. If I go back through the call
stack, it's there as well, and the caps match, the strings match. So
yes, iter might be set to end, but it's still failing to find the
lexographically equivalent value.

Re: Stl map and CString trouble by Duane

Duane
Fri Oct 03 11:04:35 CDT 2008

>it returns a bad ptr according to Visual Studio. This is failing to
>find a value that I know is in there (on the line of the find, I've
>printed out the map before and the value is there (lexographically).

find() returns an iterator, not a pointer. I think that you mean in
your debugger when you inspect it you see badptr. How are
you printing out the map to see the values?

You do know that if you do something like:

cout << g_VarMap["doh"] ;

and there was nothing at "doh" that there is now
a default value at "doh"? The [] creates a
default entry in the map if it doesn't exist.
This is why you need to either use find() or
iterate through the map.

Maybe this is what's happening?

>I've answered you in both of my posts on this. My map is a pointer
>because it is on the heap.
>g_VarMap = new std::map<string, byte *>();

>and I want it on the heap. That was very intentional.

It's odd to do that but if you have a reason...


>my byte is an unsigned byte. I have a pointer because I'm storing a
>location in a chuck of them defined as follows:
>g_VarSpace = new byte[iVarSpaceSize]; //Allocate the variable space.

OK.

>> Your aggregate looking init that you show doesn't compile for me.
>> I would expect to have to use boost::assign or something to do that.

>My what?

The part where you show
g_VarMap [5](("AA",0x003a9e0b ""),("BB",0x003a9e1b ""),("XX",
0x003a9c95 ""),("YAR",0x003a9c96 ""),("YY",0x003a9c94 ""))


>> That's why I asked what would happen if you use a map created on
>> the stack.

>Okay, I missed that that was what you wanted me to do. When I ran it,
>I did switch to strings but it was still on the heap.

Well I don't think the problem is that the map is on the
heap as long as it is being initialized and filled properly.
It's just that I never use std::containers on the heap.
I don't see any benefit with that and a lot of possible
confusion.

>I think regardless of which it is (and yes, I will check for end), it
>is failing to find the string in there, in this manufactured test case
>when I'm searching for something I know is in there, and it is when I
>print it out just before the find. If I go back through the call
>stack, it's there as well, and the caps match, the strings match. So
>yes, iter might be set to end, but it's still failing to find the
>lexographically equivalent value.

I imagine that CString is fine as a map key. Anyway, you seem to have
the same issue with std::string. I'm not sure what the actual cause
is then. I do see that in your sample you're using a few c-style casts
and such. I'd start looking at that. I'd probably also start with the
map on the stack and try filling it and inspecting it in small iterations
until the problem showed up.

I would also verify that find() is failing to find the entry. This
would indicate that it's either being inserted incorrectly or
being erased.

Which version of VS are you using?



Re: Stl map and CString trouble by Scoots

Scoots
Fri Oct 03 11:28:33 CDT 2008

Alright, I'll try to respond, but I might miss some of your points.

Quickie, that "aggregate init" was actually debug output. Here's my
watch window.
- g_VarMap [5](("AA",0x003a9e0b ""),("BB",0x003a9e1b ""),("XX",
0x003a9c95 ""),("YAR",0x003a9c96 ""),("YY",0x003a9c94 ""))
std::map<ATL::CStringT<char,ATL::StrTraitATL<char,ATL::ChTraitsCRT<char>
> >,unsigned char
*,std::less<ATL::CStringT<char,ATL::StrTraitATL<char,ATL::ChTraitsCRT<char>
> >
>,std::allocator<std::pair<ATL::CStringT<char,ATL::StrTraitATL<char,ATL::ChT