WindowsでCMakeで生成されたDLLファイルで紛らわしい問題に遭遇しました。私のライブラリでは、不思議なことに繰り返し発生するテンプレートパターンを使用して、特定のクラスに一意のID番号を付けています。
// 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
Foo :: getTypeID()を中断して、GDBを実行すると、「msTypeId」と「Foo::msTypeId」のメモリアドレスが異なることがわかりました。 なんてこったい。
ただし、これはFooがDLLで定義されている場合にのみ発生します。(そして、Windows 7でのみ、明らかに-Debianビルドではこの問題は発生しません)main.cpp内に派生クラスを作成する場合、またはライブラリからすべてのコードを実行可能ファイルにコンパイルする場合は、スキップします。 DLLステップは完全に、問題なく動作します。
すべてがMSYSとMinGWを使用してコンパイルされ、Windows 7HomePremiumではGCC4.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})