Access Violation with map<string,xxx> 
Author Message
 Access Violation with map<string,xxx>

Hello,
My dll have a template Class:
//##ModelId=3B4C5F6D00DF
template<class T>
class  CSgDictionaryStringImpl : public CSgObject
{
public:
        CSgDictionaryStringImpl();
        virtual ~CSgDictionaryStringImpl();
        virtual T* getAt(const std::string& key) const;
        virtual Sag::ErrorStatus setAt(LPCTSTR key, T*
pDictEntry);
        virtual Sag::ErrorStatus remove(const std::string&
key);
        virtual Sag::ErrorStatus removeAll();
private:
         std::map< std::string, T* >* m_pMapDictEntry;

Quote:
};

and my setAt member function implementation is:
template<class T> Sag::ErrorStatus
CSgDictionaryStringImpl< T >::setAt(const std::string&
key, T* pDictEntry)
{
        (*m_pMapDictEntry)[key] = pDictEntry;
        return Sag::eOk;
Quote:
}

and my destructor call this member function:
template<class T> Sag::ErrorStatus
CSgDictionaryStringImpl< T >::removeAll()
{
        std::map<std::string, T*>::iterator iteratorMap;
        while(!m_pMapDictEntry->empty())
        {
                iteratorMap = m_pMapDictEntry->begin();
                T* pObj = NULL;
                pObj = (*iteratorMap).second;
                delete pObj;
                pObj = NULL;
                iteratorMap = m_pMapDictEntry->erase
(iteratorMap);
        }
        return Sag::eOk;

Quote:
}

When I unload my dll I have an access violation.
But when I change my setAt member function, I didnt have
any access violation:
template<class T> Sag::ErrorStatus
CSgDictionaryStringImpl< T >::setAt(const std::string&
key, T* pDictEntry)
{
        (*m_pMapDictEntry)[key.c_str()] = pDictEntry;
        return Sag::eOk;

Quote:
}

very strange.
Anyone know how is the problem????????????????

Thanks,
Aragao



Sun, 18 Jan 2004 02:32:57 GMT  
 Access Violation with map<string,xxx>


Quote:
> Hello,
> My dll have a template Class:
> //##ModelId=3B4C5F6D00DF
> template<class T>
> class  CSgDictionaryStringImpl : public CSgObject
> {
> public:
>      CSgDictionaryStringImpl();
>      virtual ~CSgDictionaryStringImpl();
>      virtual T* getAt(const std::string& key) const;
>      virtual Sag::ErrorStatus setAt(LPCTSTR key, T*
> pDictEntry);
>      virtual Sag::ErrorStatus remove(const std::string&
> key);
>      virtual Sag::ErrorStatus removeAll();
> private:
>       std::map< std::string, T* >* m_pMapDictEntry;
> };

<snip>

Quote:
> When I unload my dll I have an access violation.
> But when I change my setAt member function, I didnt have
> any access violation:

<snip>

DLL and EXE don't share the same heap: Every one has its own heap. When
you execute code in EXE, this code allocate or deallocate memory from
EXE heap, and when you execute code from DLL, the DLL heap is used.

In setAt() function, you pass pointer to objects created in EXE code
(allocated in EXE heap), and in removeAll(), yo extract those pointer
and delete thems from DLL code (deallocated from DLL heap).

?Is this the problem?

Gonzalo.



Sun, 18 Jan 2004 16:16:50 GMT  
 Access Violation with map<string,xxx>
Hi Gonzalo,
In My Dll I have an Class Singleton:
class SSAGREDLLIMPEXP CSgApp
{
public:
        static Sag::ErrorStatus registerApp(const
std::string& strModuleName, CSgApp* pApp);
        virtual Sag::ErrorStatus initialize();
        virtual Sag::ErrorStatus finalize();
        static CSgApp* instance();
        CSgDictionary* getMainDictionary();
        Sag::ErrorStatus getModuleName(std::string&
strModuleName);
protected:
        CSgApp();
        virtual ~CSgApp();
        Sag::ErrorStatus setModuleName(const std::string&
strModuleName);

private:
        static CSgApp* m_pApp; //static member
        std::string m_strModuleName;
        CSgDictionary* m_pDict;

Quote:
};

/////////////////Arquivo CSgApp.cpp/////////////////////
CSgApp* CSgApp::m_pApp = NULL;

CSgApp::CSgApp() : m_strModuleName(""),m_pDict(NULL)
{
        m_pDict = new CSgDictionary;

Quote:
}

Sag::ErrorStatus
CSgApp::initialize()
{
        return Sag::eOk;

Quote:
}

//##ModelId=3AC0CDDD036D
Sag::ErrorStatus
CSgApp::finalize()
{      
        delete m_pDict;
        //delete m_pApp;
        return Sag::eOk;

Quote:
}

CSgApp::~CSgApp()
{

Quote:
}

Sag::ErrorStatus
CSgApp::setModuleName(const std::string& strModuleName)
{
        //m_strModuleName = strModuleName.c_str();
        m_strModuleName = strModuleName;
        return Sag::eOk;

Quote:
}

Sag::ErrorStatus
CSgApp::getModuleName(std::string& strModuleName)
{
        strModuleName = m_strModuleName;
        return Sag::eOk;

Quote:
}

CSgDictionary*
CSgApp::getMainDictionary()
{
        return m_pDict;

Quote:
}

CSgApp* CSgApp::instance()
{
        return m_pApp;

Quote:
}

Sag::ErrorStatus
CSgApp::registerApp(const std::string& strModuleName,
CSgApp* pApp)
{
        if(m_pApp) return Sag::eAppWasCreated;
        m_pApp = pApp;
        m_pApp->setModuleName(strModuleName);
        return Sag::eOk;

Quote:
}

where m_pDict is derived from
template<CSgObject> class  CSgDictionaryStringImpl.
Access violation happen on
CSgDictionaryStringImpl<CSgObject>::removeAll() that is
called on destructor ~CSgDictionaryStringImpl<CSgObject>.
the member variable m_pDict is created on CSgApp
constructor(on DLL???)

On my EXE I have a Class CSgAcBasicApp derived from
Singleton CSgApp:
class CSgAcBasicApp : public CSgApp
{
public:
        virtual ~CSgAcBasicApp();
        CSgAcBasicApp();

Quote:
};

On My exe I have a factory that Create an instance of
CSgAcBasicApp:
Sag::ErrorStatus
CSgAcBasicAppFactory::createApplication()
{      
        CSgAcBasicApp* pApp = new CSgAcBasicApp();
        if(pApp == NULL) return Sag::eOutOfMemory;
        Sag::ErrorStatus es = CSgApp::registerApp
("Sagre/Cad", pApp);
        if(es != Sag::eOk)
        {
                delete pApp;
                return es;
        }
        return es;

Quote:
}

So, when I unload my Exe I call the virtual
function CSgAcBasicApp::finalize() that was defined
on CSgApp::finalize() and CSgApp::finalize just call the
dictionary destructor.

Really I Dont know what is happening.
This is an STL limitation or I am making mistakes???

Thanks,
Aragao

Quote:
>-----Original Message-----



Quote:

>> Hello,
>> My dll have a template Class:
>> //##ModelId=3B4C5F6D00DF
>> template<class T>
>> class  CSgDictionaryStringImpl : public CSgObject
>> {
>> public:
>>      CSgDictionaryStringImpl();
>>      virtual ~CSgDictionaryStringImpl();
>>      virtual T* getAt(const std::string& key) const;
>>      virtual Sag::ErrorStatus setAt(LPCTSTR key, T*
>> pDictEntry);
>>      virtual Sag::ErrorStatus remove(const std::string&
>> key);
>>      virtual Sag::ErrorStatus removeAll();
>> private:
>>       std::map< std::string, T* >* m_pMapDictEntry;
>> };

><snip>

>> When I unload my dll I have an access violation.
>> But when I change my setAt member function, I didnt
have
>> any access violation:

><snip>

>DLL and EXE don't share the same heap: Every one has its
own heap. When
>you execute code in EXE, this code allocate or deallocate
memory from
>EXE heap, and when you execute code from DLL, the DLL
heap is used.

>In setAt() function, you pass pointer to objects created
in EXE code
>(allocated in EXE heap), and in removeAll(), yo extract
those pointer
>and delete thems from DLL code (deallocated from DLL
heap).

>?Is this the problem?

>Gonzalo.
>.



Sun, 18 Jan 2004 20:41:12 GMT  
 Access Violation with map<string,xxx>


I'm almost sure the problem is copying strings.

??Warning!! STL strings are referenced. When you copy a string:

string a(b);

both reference the same string and a counter is incremented.

When the destructor is invoked, de counter is decremented, and the las
destructor free the memory.

When you pass a string from EXE to DLL, if string is copied, DLL don't
alloc memory:

setAt(const string& key)
{
    my_map[key] = something; // the string is not copied, but
                             // incremented reference

Quote:
}

But if you dont use more the string in EXE, the destructor is invoked
and the reference is decremented.

If DLL code is the last invoking string destructor:

removeAll()
{
   my_map.erase(my_map.begin()); // the element destructor in map is
                                 // invoked, the key destructor is
                                 // invoked too.

Quote:
}

if is the last instance of string, string::~string() try dealloc memory
from its heap: Access Violation!!

?What is the solution? Don't use STL static link, use STL dynamic link.
Both code, EXE and DLL will use STL in MSVCRT.DLL (I don't remember the
exact name), the constructor and destructor code of string will in the
same location. In your projects settings you can specify you want link
dynamic runtime libs.

Perhaps you need define macro EXP_STL in your settings too.

Gonzalo.



Mon, 19 Jan 2004 18:11:41 GMT  
 Access Violation with map<string,xxx>
Hi Gonzalo,
Thanks for your reply.
I think that this is the problem.
To say the truth, I didnt have One exe and one dll, but 2
dlls.
My Application is a third part application(run on Autocad-
cad product-acad.exe), so I have two dlls that run on
acad.exe.
To build dlls that run on Autocad I have to use a pre
defined project configuration. For exemple I have to use
the option "Multithreaded DLL"(Applications compiled with
this option are statically linked to MSVCRT.LIB).
So I dont know how can I solve this problem yet.
PS: I am using the EXP_STL macro.

Cheers,
Aragao

Quote:
>-----Original Message-----


>I'm almost sure the problem is copying strings.

>??Warning!! STL strings are referenced. When you copy a
string:

>string a(b);

>both reference the same string and a counter is
incremented.

>When the destructor is invoked, de counter is

decremented, and the las
Quote:
>destructor free the memory.

>When you pass a string from EXE to DLL, if string is
copied, DLL don't
>alloc memory:

>setAt(const string& key)
>{
>    my_map[key] = something; // the string is not copied,
but
>                             // incremented reference
>}

>But if you dont use more the string in EXE, the

destructor is invoked
Quote:
>and the reference is decremented.

>If DLL code is the last invoking string destructor:

>removeAll()
>{
>   my_map.erase(my_map.begin()); // the element

destructor in map is
Quote:
>                                 // invoked, the key
destructor is
>                                 // invoked too.
>}

>if is the last instance of string, string::~string() try
dealloc memory
>from its heap: Access Violation!!

>?What is the solution? Don't use STL static link, use STL
dynamic link.
>Both code, EXE and DLL will use STL in MSVCRT.DLL (I
don't remember the
>exact name), the constructor and destructor code of
string will in the
>same location. In your projects settings you can specify
you want link
>dynamic runtime libs.

>Perhaps you need define macro EXP_STL in your settings
too.

>Gonzalo.
>.



Mon, 19 Jan 2004 19:35:57 GMT  
 Access Violation with map<string,xxx>


Quote:
> To build dlls that run on Autocad I have to use a pre
> defined project configuration. For exemple I have to use
> the option "Multithreaded DLL"(Applications compiled with
> this option are statically linked to MSVCRT.LIB).
> So I dont know how can I solve this problem yet.
> PS: I am using the EXP_STL macro.

> Cheers,
> Aragao

Miltihreaded DLL link to MSVCRT.LIB, but it's a "gateway" (I don't know
what is the technical word for it) to code contained in MSVCRT.DLL (This
code include string and wstring templates instantation).

Perhaps you found more help in MSDN Knoledgement Base: Q168958 "HOWTO:
Exporting STL Components Inside & Outside of a Class" and Q172396 "PRB:
Accedd Violation When Accesing STL Object in DLL".

A question: Is the class interface imposed by Autocad? In your owned
interfaces, you can try avoid the problematic class. In Autocad
interfaces, you must try avoid copying strings.

You can create a new string without references:

aFunction(const string& str)
{
  // create a NEW string and copy the string passed,
  // it didn't reference to string passed.
  string MyStr(str.c_str());

Quote:
}

Luck!

Gonzalo.



Mon, 19 Jan 2004 22:31:23 GMT  
 Access Violation with map<string,xxx>
Hi Gonzalo,
I have read microsot articles on the past and my code is
compliant with it.

The class interface is not imposed by Autocad.
I just want clarify this point for 2 reasons:
a)- My setAt funcion works with
 "(*m_pMapDictEntry)[tempKey.c_str()]= pDictEntry;",but
dont work with "(*m_pMapDictEntry)[tempKey] =
pDictEntry;". So I am not sure if I solved my problem with
c_str() or just I am hidding my problem.

b)- I Cant use my template class (template<typename KEY,
class T>class  CSgDictionaryImpl) because my
CSgDictionaryImpl<KEY,T>::setAt is defined:
template<typename KEY, class T> Sag::ErrorStatus
CSgDictionaryImpl<KEY, T>::setAt(const KEY& key, T*
pDictEntry)
{
        (*m_pMapDictEntry)[tempKey] = pDictEntry;      
        return Sag::eOk;

Quote:
}

So, to solve this problem, I had to create another
template class (template<class T>class  
CSgDictionaryStringImpl) with just one difference :
CSgDictionaryStringImpl<T>::setAt(const std::string& key,
T* pDictEntry)
{
        (*m_pMapDictEntry)[tempKey.c_str()] = pDictEntry;

        return Sag::eOk;

Quote:
}

But if the problem is string reference count, I dont mind
to use this approach.

One more time, Thanks for your support.

Cheers,
Aragao

Quote:
>Miltihreaded DLL link to MSVCRT.LIB, but it's a "gateway"
(I don't know
>what is the technical word for it) to code contained in
MSVCRT.DLL (This
>code include string and wstring templates instantation).

>Perhaps you found more help in MSDN Knoledgement Base:
Q168958 "HOWTO:
>Exporting STL Components Inside & Outside of a Class" and
Q172396 "PRB:
>Accedd Violation When Accesing STL Object in DLL".

>A question: Is the class interface imposed by Autocad? In
your owned
>interfaces, you can try avoid the problematic class. In
Autocad
>interfaces, you must try avoid copying strings.

>You can create a new string without references:

>aFunction(const string& str)
>{
>  // create a NEW string and copy the string passed,
>  // it didn't reference to string passed.
>  string MyStr(str.c_str());
>}

>Luck!

>Gonzalo.
>.



Tue, 20 Jan 2004 00:46:53 GMT  
 Access Violation with map<string,xxx>


Hi Aragao.

Quote:
> a)- My setAt funcion works with
>  "(*m_pMapDictEntry)[tempKey.c_str()]= pDictEntry;",but
> dont work with "(*m_pMapDictEntry)[tempKey] =
> pDictEntry;". So I am not sure if I solved my problem with
> c_str() or just I am hidding my problem.

If you use c_str() you hide the problem, I'm afraid, because you use a
pointer as key the, but not the array of char. The pointer can or can
not reference to a valid array of char.

Quote:
> b)- I Cant use my template class (template<typename KEY,
> class T>class  CSgDictionaryImpl) because my
> CSgDictionaryImpl<KEY,T>::setAt is defined:
> template<typename KEY, class T> Sag::ErrorStatus
> CSgDictionaryImpl<KEY, T>::setAt(const KEY& key, T*
> pDictEntry)
> {
>      (*m_pMapDictEntry)[tempKey] = pDictEntry;    
>      return Sag::eOk;
> }
> So, to solve this problem, I had to create another
> template class (template<class T>class  
> CSgDictionaryStringImpl) with just one difference :
> CSgDictionaryStringImpl<T>::setAt(const std::string& key,
> T* pDictEntry)
> {
>      (*m_pMapDictEntry)[tempKey.c_str()] = pDictEntry;

>      return Sag::eOk;
> }

I see. Is a ugly solution redefine setAt method. Perhaps you need create
a new type wrapping string class. For example:

class NewString
{
public:
  NewString(): m_str(0);

  NewString(const NewString& rhs)
  {
    if (strlen(rhs()))
    {
      m_str = new char [strlen(rhs()) + 1];
      m_str[strlen(rhs())] = '\0';
    }
  }
  NewString(const string& str)
  {
    m_str = new char[str.length() + 1];
    m_str[str.length()] = '\0';
  }

  ~NewString()
  {
    if (m_str) delete[] m_str;
  }

  bool operator <(const NewString& rhs) const
  {
    return strcmp(m_str, rhs()) < 0;
  }

  const char * operator ()() const
  {
    return m_str;
  }

Quote:
}

And then you can use CSgDictionaryImpl<NewString, T>.

Now, you can do:

string a("Peter);
dict.setAt(a, something);

because there is a constructor from string to NewString.

But the New string is not transparent, I'm affraid. You need use:

NewString b;
string a(b()); // or string a = b();

It's an idea.

Gonzalo.



Tue, 20 Jan 2004 16:37:59 GMT  
 Access Violation with map<string,xxx>
Hi Gonzalo,
I didnt understand when you said that I use  a
pointer as key. My Dictionaries implementation
(CSgDictionaryImpl and CSgStringDictionaryImpl) encapsulate
the class std::map. Your member variables is std::map<KEY,
T* >* m_pMapDictEntry and std::map<std::string, T* >*
m_pMapDictEntry; So, when I instantiate my
CSgDictionaryImpl with std::string and CSgObject I have a
member variable std::map<std::string, CSgObject*>

I know that is ugly the solution with
CSgDictionaryStringImpl. But, Do you think that I will
have problem using c_str()?

Your string class is a good idea. But I would like to use
stl library yet. On my implementation, I use a lot of
std::string member functions.
Maybe another solution is have  a new string class derived
from std::string and implement de copy constructor and
operator= to alocate another space memory, how do you did
on your implementation class string.

But if with c_str() I will not have problem, I prefer use
it.

Cheers,
Aragao

Quote:
>-----Original Message-----


>Hi Aragao.

>> a)- My setAt funcion works with
>>  "(*m_pMapDictEntry)[tempKey.c_str()]= pDictEntry;",but
>> dont work with "(*m_pMapDictEntry)[tempKey] =
>> pDictEntry;". So I am not sure if I solved my problem
with
>> c_str() or just I am hidding my problem.

>If you use c_str() you hide the problem, I'm afraid,
because you use a
>pointer as key the, but not the array of char. The
pointer can or can
>not reference to a valid array of char.

>> b)- I Cant use my template class (template<typename
KEY,
>> class T>class  CSgDictionaryImpl) because my
>> CSgDictionaryImpl<KEY,T>::setAt is defined:
>> template<typename KEY, class T> Sag::ErrorStatus
>> CSgDictionaryImpl<KEY, T>::setAt(const KEY& key, T*
>> pDictEntry)
>> {
>>      (*m_pMapDictEntry)[tempKey] = pDictEntry;    
>>      return Sag::eOk;
>> }
>> So, to solve this problem, I had to create another
>> template class (template<class T>class  
>> CSgDictionaryStringImpl) with just one difference :
>> CSgDictionaryStringImpl<T>::setAt(const std::string&
key,
>> T* pDictEntry)
>> {
>>      (*m_pMapDictEntry)[tempKey.c_str()] = pDictEntry;

>>      return Sag::eOk;
>> }

>I see. Is a ugly solution redefine setAt method. Perhaps
you need create
>a new type wrapping string class. For example:

>class NewString
>{
>public:
>  NewString(): m_str(0);

>  NewString(const NewString& rhs)
>  {
>    if (strlen(rhs()))
>    {
>      m_str = new char [strlen(rhs()) + 1];
>      m_str[strlen(rhs())] = '\0';
>    }
>  }
>  NewString(const string& str)
>  {
>    m_str = new char[str.length() + 1];
>    m_str[str.length()] = '\0';
>  }

>  ~NewString()
>  {
>    if (m_str) delete[] m_str;
>  }

>  bool operator <(const NewString& rhs) const
>  {
>    return strcmp(m_str, rhs()) < 0;
>  }

>  const char * operator ()() const
>  {
>    return m_str;
>  }
>}

>And then you can use CSgDictionaryImpl<NewString, T>.

>Now, you can do:

>string a("Peter);
>dict.setAt(a, something);

>because there is a constructor from string to NewString.

>But the New string is not transparent, I'm affraid. You
need use:

>NewString b;
>string a(b()); // or string a = b();

>It's an idea.

>Gonzalo.

>.



Tue, 20 Jan 2004 19:40:03 GMT  
 Access Violation with map<string,xxx>
Hi Aragao.



<snip>

Quote:
> I know that is ugly the solution with
> CSgDictionaryStringImpl. But, Do you think that I will
> have problem using c_str()?

<snip>

I don't know you'll have problem using c_str() but I think you'll can
have it. c_str() return a const char *, a pointer to array of char. This
pointer is valid while the array is allocated in memory, and the array
is in memory while there are any string reference.

For example:

void a_function(T *p)
{
  string str("some key");
  dict->setAt(str, p);

Quote:
}

void another_function()
{
  string str("some key");
  T *p = dict->getAt(str);

Quote:
}

In this example, the strings used as key are defined locally. In
a_function(), Dictionary class use str.c_str() as map key. c_str() is a
pointer to memory allocated by str defined in a_function(). Exiting of
function, str destructor is invoked and, in this case (only string
reference it), memory is deallocated, and map has a pointer to
deallocated memory as key.

In another_function(), then new string allocate memory for "some key",
and that memory can not match with key pointer in map, and you'll not
get the dictionary entry.

If str is a global variable, and the string you pass to both
CsgDictionaryStringImpl methods reference to the same memory (string is
reference count), you'll not any problem.

I think if you redefine setAt() and getAt() for use c_str(), is better
redefine so:

CSgDictionaryStringImpl< T >::setAt(
  const std::string& key,
  T* pDictEntry)
{
        // Create a new string but don't invoke copy constructor
      string newKey(key.c_str(), key.length());
        // The new string is the key
        (*m_pMapDictEntry)[newKey] = pDictEntry;
        return Sag::eOk;

Quote:
}

T* CsgDictionaryStringImpl<T>::getAt(
  const std::string& key) const
{
  string newKey(key.c_str(), key.length());
  ...

Quote:
}

Now:
- you use STL string in interface and in implementation,
- is safe with independece of the class client code,
- it has not problem with DLLs heaps.

What do you think of this?

Gonzalo.



Tue, 20 Jan 2004 20:14:53 GMT  
 Access Violation with map<string,xxx>
Hi Aragao.

I think I didn't understand you when you proposed using c_str().

If you use map<std::string, CsgObject *> and insert elements:

(*m_pMapDicEntry)[str.c_str()];

the implicit string(const char *) implicit constructor is called and
copy without count reference is done.

It's all right. I'm sorry.

Greetings.

Gonzalo.



Fri, 23 Jan 2004 15:49:02 GMT  
 
 [ 11 post ] 

 Relevant Pages 

1. <string>,memory access violation

2. Warnings using STL Map<string,string>

3. <<<<<<<Parsing help, please>>>>>>>>

4. Access Violation in <xlocale>

5. File Format conversion, ascii freeform -->.csv <-->.wk1<-->dbf<-->?HELP

6. STL map<string, IHTMLElement*> Elements

7. <<<>>>Need C code advice with functions and sorting.<<<>>>

8. <><><>HELP<><><> PCMCIA Motorola Montana 33.6

9. <<<XXX Secret Password>>>

10. <<<An XXX Password>>>

11. >>>Windows Service<<<

12. what *An_Iterator in map<xxx,xxx>::iterator returns ?

 

 
Powered by phpBB® Forum Software