gpt4 book ai didi

c++ - 没有被引用的静态对象不会在静态库的情况下被创建?

转载 作者:行者123 更新时间:2023-11-28 08:18:55 25 4
gpt4 key购买 nike

开发环境GNU GCC (g++) 4.1.2,CMAKE

在我读了 James Coplien 的一本名为“Advanced C++ Programing Styles and Idioms”的权威书籍之后(我必须承认这本书很老了。所以你们中的一些人可能会觉得它有点过时了。),我发现了“Exemplar idiom”对于削弱继承类层次结构之间的相互依赖性非常有用。所以尝试创建一个简单的项目来处理这个成语,如下所示。

预先感谢您的耐心等待,我将完整的源代码列出如下。

在 CMakeLists.txt 中

cmake_minimum_required(VERSION 2.6)

project(TestProject)

add_library(exemplar_idiom STATIC base.cpp derived1.cpp)

add_executable(exemplar_example main.cpp)
target_link_libraries(exemplar_example exemplar_idiom)
set_target_properties(exemplar_example PROPERTIES OUTPUT_NAME exemplar_example)

在范例.h中

#ifndef EXEMPLAR_H_
#define EXEMPLAR_H_

class Exemplar
{
public:
Exemplar() {};
};

#else
#endif // EXEMPLAR_H_

在base.h中

#ifndef BASE_H_
#define BASE_H_

#include <string>

class Exemplar;

class Base
{
public:
Base(Exemplar /* no use */);
Base();

virtual Base* make(const std::string& key);

virtual void memberMethod1();
virtual int memberMethod2();

virtual ~Base() {};
protected:
static Base* list_;
Base* next_;

};

#else
#endif // BASE_H_

在base.cpp中

#include <string>
#include <iostream>

#include "exemplar.h"
#include "base.h"

Base* Base::list_ = 0;
static Exemplar exemplar;
static Base baseInstance(exemplar);
Base* baseExemplar = &baseInstance;

Base::Base(Exemplar /* no use */) : next_(list_)
{
std::cout << "Base object exemplar ctor" << std::endl;
list_ = this;
}

Base::Base() : next_(0) {}

Base* Base::make(const std::string& key)
{
Base* retval = 0;

for (Base* a = list_; a; a = a->next_)
{
if (a != baseExemplar)
{
if ((retval = a->make(key)))
{
break;
}
}
else if (key == "base")
{
retval = new Base();
break;
}
}
return retval;
}

void Base::memberMethod1()
{
std::cout << "base class memberMethod1() called." << std::endl;
}

int Base::memberMethod2()
{
std::cout << "base class memberMethod2() called." << std::endl;
return 0;
}

在derived1.h中

#include "base.h"

#ifndef DERIVED1_H_
#define DERIVED1_H_

class Exemplar;

class Derived1 : public Base
{
public:
Derived1(Exemplar /* no use */);

// Conventional default constructor which will be used to instantiate normal object
Derived1();

virtual Derived1* make(const std::string& key);
virtual void memberMethod1();
virtual int memberMethod2();
};

#else
#endif // DERIVED1_H_

在derived1.cpp中

#include <iostream>

#include "exemplar.h"
#include "derived1.h"

static Exemplar exemplar;
static Derived1 derived1Exemplar(exemplar);

Derived1::Derived1(Exemplar a) : Base(a)
{
std::cout << "Derived object exemplar ctor" << std::endl;
}

Derived1::Derived1() : Base() {}

Derived1* Derived1::make(const std::string& key)
{
Derived1* retval = 0;
if (key == "derived1")
{
retval = new Derived1();
}
return retval;
}

void Derived1::memberMethod1()
{
std::cout << "Derived1::memberMethod1" << std::endl;
}

int Derived1::memberMethod2()
{
/* dummy */
std::cout << "Derived1::memberMethod2" << std::endl;
return 0;
}

在 main.cpp 中

#include "base.h"

extern Base* baseExemplar;

int main()
{
Base *ptr = baseExemplar->make("derived1");
if (ptr) {
ptr->memberMethod1();
ptr->memberMethod2();
}

Base *ptr2 = baseExemplar->make("base");
if (ptr2) {
ptr2->memberMethod1();
ptr2->memberMethod2();
}

return 0;
}

当我们稍微更改 CMakeLists.txt 以通过将关键字“STATIC”替换为“SHARED”来创建共享对象时,我可以看到我预期的行为。我可以看到,作为 Derived1 类对象(带有 Exemplar arg)的静态对象创建的结果,Base 类中的链接列表链得到了正确维护。之后,当从 main() 中的基础示例对象调用虚拟 make() 方法时,我可以看到通过指定“derived1”和“base”的键字符串成功创建了 Derived1 对象和 Base 对象。

但是,如果我将关键字“SHARED”恢复为“STATIC”,那么我会看到不同的结果。似乎根本没有创建这样的静态对象(Derived1 示例对象)。所以调用make("derived1")成员方法创建Derived1对象失败。

有什么办法可以避免这个问题,即使是在静态库的情况下?我希望静态对象构造函数对基类的链接列表产生副作用。

我不确定我在这里尝试做的事情对您是否有意义。但是,如果您能就上述内容给我指点,我们将不胜感激。

最佳答案

是的,GNU 链接器 ld 只添加它认为实际使用的那些符号。 ld 只能检查符号是否在使用中,而不能检查符号初始化的副作用是否被使用。

因此,结果将是像您这样的情况,由于未使用的静态对象未初始化而导致失败。

您可以在链接时使用--whole-archive 告诉链接器包含所有符号。缺点是您不想使用的符号也会被添加并导致代码大小增加。

还有一点需要注意的是:

只有当未使用的目标文件来自库时,链接器才会删除它们。明确传递给链接器的目标文件将始终被链接。

关于c++ - 没有被引用的静态对象不会在静态库的情况下被创建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6668973/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com