我在Windows上遇到了CMake生成的DLL文件的混淆問題。在我的圖書館,我用奇異遞歸模板模式給予一定等級的唯一ID號:CMake生成的DLL和奇怪的循環模板的錯誤行爲(C++)
// da/Attribute.h:
#ifndef DA_ATTRIBUTE_H
#define DA_ATTRIBUTE_H
namespace da {
typedef unsigned int AttributeId;
class AttributeBase {
public:
virtual AttributeId getTypeId() const=0;
protected:
/** Static ID counter. Every class that derives da::AttributeBase is
assigned an increment of this counter as its type ID number */
static AttributeId sNextId;
};
template <class Derived>
class Attribute : public AttributeBase {
private:
static AttributeId msTypeId;
public:
Attribute() {
if (msTypeId == 0) {
msTypeId = ++sNextId;
}
}
virtual ~Attribute() {
}
/** For static contexts */
static AttributeId typeId() {
if (msTypeId == 0) {
msTypeId = ++sNextId;
}
return msTypeId;
}
AttributeId getTypeId() const {
return typeId();
}
};
template <class Derived> AttributeId Attribute<Derived>::msTypeId = 0;
}
#endif
問題是,當我的DLL鏈接到一個可執行的項目,似乎有一些不一致的地方用不同的ID方法。例如:
// Foo.h
struct Foo : public da::Attribute<Foo> {
Foo() { }
};
...
// main.cpp
Foo *foo = new Foo;
Foo->getTypeId() == 1 // True
Foo::typeId() == 1 // Should be true, but isn't. Foo::typeId() == 2
運行通過與GDB,在富:: getTypeID(),休息,我發現 「msTypeId」 和 「Foo :: msTypeId」有不同的內存地址。到底是什麼。
這隻發生在Foo被定義在DLL中時。 (並且只有在Windows 7中,顯然 - 我的Debian版本中沒有這個問題)如果我在main.cpp中創建派生類,或者只是將庫中的所有代碼編譯到可執行文件中,跳過DLL完全步驟,它沒有問題。
所有內容均使用MSYS和MinGW編譯,並在Windows 7 Home Premium上使用GCC 4.7編譯。
下面是庫中的CMakeLists.txt,萬一我搞砸了的東西有:
cmake_minimum_required(VERSION 2.6)
project(foo)
add_definitions(-std=c++0x)
set(CMAKE_BUILD_TYPE Debug)
set(sources
Foo.cpp
)
add_library(foo SHARED ${sources})