Access Violation When Accessing an STL Object Through A Pointer or Reference In A Different DLL or E
- by Yan Cheng CHEOK
I experience the following problem while using legacy VC6. I just cann't switch to modern compiler, as I am working on a legacy code base.
http://support.microsoft.com/kb/172396
Since there are no way to export map, my planned workaround is using static linking instead of dynamic linking.
I was wondering whether you all had encountered the similar situation? What is your workaround for this?
Another workaround is to create wrapper class around the stl map, to ensure creation and accessing stl map, are within the same DLL space. Note that, fun0, which uses wrapper class will just work fine. fun1 will crash.
Here is the code example :
// main.cpp. Compiled it as exe.
#pragma warning (disable : 4786)
#include <map>
#include <string>
template <class K, class V>
class __declspec(dllimport) map_wrapper {
public:
map_wrapper();
~map_wrapper();
map_wrapper(const map_wrapper&);
map_wrapper& operator=(const map_wrapper&);
V& operator[](const K&);
const V& operator[](const K&) const;
const V& get(const K&) const;
void put(const K&, const V&);
int size() const;
private:
std::map<K, V> *m;
};
__declspec(dllimport) void fun0(map_wrapper<std::string, int>& m);
__declspec(dllimport) void fun1(std::map<std::string, int>& m);
int main () {
map_wrapper<std::string, int> m0;
std::map<std::string, int> m1;
m0["hello"] = 888;
m1["hello"] = 888;
// Safe. The we create std::map and access map both in dll space.
fun0(m0);
// Crash! The we create std::map in exe space, and access map in dll space.
fun1(m1);
return 0;
}
// dll.cpp. Compiled it as dynamic dll.
#pragma warning (disable : 4786)
#include <map>
#include <string>
#include <iostream>
/* In map_wrapper.h */
template <class K, class V>
class __declspec(dllexport) map_wrapper {
public:
map_wrapper();
~map_wrapper();
map_wrapper(const map_wrapper&);
map_wrapper& operator=(const map_wrapper&);
V& operator[](const K&);
const V& operator[](const K&) const;
const V& get(const K&) const;
void put(const K&, const V&);
int size() const;
private:
std::map<K, V> *m;
};
/* End */
/* In map_wrapper.cpp */
template <class K, class V>
map_wrapper<K, V>::map_wrapper() : m(new std::map<K, V>()) {
}
template <class K, class V>
map_wrapper<K, V>::~map_wrapper() {
delete m;
}
template <class K, class V>
map_wrapper<K, V>::map_wrapper(const map_wrapper<K, V>& map) : m(new std::map<K, V>(*(map.m))) {
}
template <class K, class V>
map_wrapper<K, V>& map_wrapper<K, V>::operator=(const map_wrapper<K, V>& map) {
std::map<K, V>* tmp = this->m;
this->m = new std::map<K, V>(*(map.m));
delete tmp;
return *this;
}
template <class K, class V>
V& map_wrapper<K, V>::operator[](const K& key) {
return (*this->m)[key];
}
template <class K, class V>
const V& map_wrapper<K, V>::operator[](const K& key) const {
return (*this->m)[key];
}
template <class K, class V>
const V& map_wrapper<K, V>::get(const K& key) const {
return (*this->m)[key];
}
template <class K, class V>
void map_wrapper<K, V>::put(const K& key, const V& value) {
(*this->m)[key] = value;
}
template <class K, class V>
int map_wrapper<K, V>::size() const {
return this->m->size();
}
// See : http://www.parashift.com/c++-faq-lite/templates.html#faq-35.15
// [35.15] How can I avoid linker errors with my template classes?
template class __declspec(dllexport) map_wrapper<std::string, int>;
/* End */
__declspec(dllexport) void fun0(map_wrapper<std::string, int>& m) {
std::cout << m["hello"] << std::endl;
}
__declspec(dllexport) void fun1(std::map<std::string, int>& m) {
std::cout << m["hello"] << std::endl;
}