tags:

views:

187

answers:

3

Hi Guys,

I am facing an interesting situation and want to share with all. Definitely, if some one can help I shall be grateful!

#include "stdafx.h"
#include <map>

#define DEF_NAME1   "NAME1" 
#define DEF_NAME2   "NAME2" 
#define DEF_NAME3   "NAME3" 
#define DEF_NAME4   "NAME4" 

struct TInfo
{
    const char * TName;
    const char * TArray1[100];
    const char * TArray2[100];
};

typedef std::map<const char*, TInfo*> TInfoMap;
typedef std::pair<const char*,TInfo*> TInfoPair;

static TInfoMap tinfomap;

TInfo TInfoArray[] =
{
{DEF_NAME1,{""}, {""}},
{DEF_NAME2,{""}, {""}},
{DEF_NAME3,{""}, {""}},
{DEF_NAME4,{""}, {""}}
};

TInfoMap* GetTInfoMap()
{

for (int i = 0; i < 3 ; i++ )
 tinfomap.insert(TInfoPair(TInfoArray[i].TName,&TInfoArray[i]));

return &tinfomap;
}


int _tmain(int argc, _TCHAR* argv[])
{
char *name="NAME3";

TInfo* ptr = new TInfo();

TInfoMap* map1 = GetTInfoMap(); 

if ( map1->find(name) == map1->end() )
 printf("Not found");
else
 printf("Found!");

return 0;
}

I am on windows 2003 Server 64bit. I get output "Found!" when I compile/run this programe in Release mode and the output is "Not found" when I complile/run this programe in Debug mode.

Any idea?

Regards,

Azher

A: 

I just tried this on my server2008 64bit box and both debug and release print "Found!".

So probably a 2003 issue of some kind. I don't have a 2003 64bit so can't try that.

Ed Sykes
+7  A: 

Try using std::string as a key in map. The problem when you're using char* as a key, map compares address of char* and not their contents as you expect. If you want use char* as a key you need to instantiate map with compare predicate a a third argument to template.

The difference between Debug and Release configuration here maybe explained how const string literals are stored - is same or separate storage is used used for the same string

You're not alone link

dimba
Thanks for the response. Then it should not work in Release mode as well. It is confusing because it works in Release mode but does not work in Debug mode.
Azher Iqbal
Thinks may work different in Debug and Release modes. This is well known problem (for example http://www.flounder.com/debug_release.htm)
dimba
idimba,Great!!!Thanks for the help
Azher Iqbal
A: 

Compiler don't have to allocate the same char constraint in the same memory. If you have char constraint in two cpp file,the address will be different.

One idea is to change map to std::map or declare with special Compare:

class CompareCString
{
  bool operator()(const char* one,const char* two) { return strcmp(one,two)>0; };
};
typedef std::map<const char*, TInfo*, CompareCString> TInfoMap;

This comparator is much slower then just comparing two pointers.You could save the pointer in static constraint.

#define DEFINE_NAME(X)   const char * X = #X ;
DEFINE_NAME(NAME1)
DEFINE_NAME(NAME2)
TInfo TInfoArray[] =
{
  {NAME1,{""}, {""}},
  {NAME2,{""}, {""}},
};

Use:

map1->find(NAME1); // it should work.

You also could make a array of const char* and change the pointer of cstring to pointer to identical cstring found in that array. Using set is good idea:

typedef set<const char *,CompareCString> IternStringSet;
const char* iternStringSetData[] = 
{
   "Name1","Name2","Name3","Name4"
};
enum IternStringNames
{
   Name1,Name2,Name3,Name4
};
IternStringSet iternStringSet(iternStringSetData,iternStringSetData+4);
const char* intern(const char* name)
{
     IternStringSet::iterator i = iternStringSet.find(name);
     return ( i=!iternStringSet.end() ) ? *i : NULL;
}
const char* intern(IternStringNames name)
{
     return iternStringSetData[name];
}

Use:

const char* what = intern("Name1"); slower ,using strcmp, but done once
map1->find( what ); // faster, not using strcmp

map1->find( intern(Name1) ); // faster, not using strcmp
lionbest