我在使用旧版 VC6 时遇到以下问题。我只是无法切换到现代编译器,因为我正在处理遗留代码库。
http://support.microsoft.com/kb/172396 http://support.microsoft.com/kb/172396
由于无法导出地图,我计划的解决方法是使用静态链接而不是动态链接。
想问问大家有遇到过类似的情况吗?您对此有何解决方法?
另一种解决方法是围绕 stl 映射创建包装类,以确保创建和访问 stl 映射位于同一 DLL 空间内。请注意,使用包装类的 fun0 可以正常工作。 fun1 会崩溃。
这是代码示例:
// 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;
}