首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >g++不依赖于优化设置进行链接

g++不依赖于优化设置进行链接
EN

Stack Overflow用户
提问于 2020-07-29 13:55:35
回答 1查看 85关注 0票数 3

所以,在过去的两天里,这件事一直折磨着我:

我无法链接我的应用程序,这取决于我使用的编译器和使用的优化级别:

  • gcc-O1-O2-O3玩得很好,但在-O0
  • clang很好地处理了-O2-O3,而-O1-O0失败了。

里面有一堆可怕的模板,但我看不出有什么理由会出现这种模糊的行为。

下面是再现问题的最少数量的代码:

代码语言:javascript
复制
#include <map>
#include <memory>
#include <iostream>

using id_type = long;

class CB : public std::enable_shared_from_this<CB>
{
public:
    CB() = default;
    virtual ~CB() = default;
};

template<class F, class C> class SC : public CB
{
};

class FB
{
public:
    virtual ~FB() = default;
    template<class T, class B> T* as(B* v) const { return dynamic_cast<T*>(v);}
};

template<class T>
class F : public FB
{
public:
    virtual std::shared_ptr<CB> create() const
    {
        auto n = std::make_shared<T>();
        return n;
    }
};

struct  B
{
    virtual ~B() = default;
    static const id_type ID = 1;
};

class A : virtual public B, virtual public SC<A, B>
{
public:
    A() = default;
};

static std::map<id_type, std::shared_ptr<FB>> crtrs {
        {A::ID, std::make_shared<F<A>>()}
    };

int main()
{
    std::cout << crtrs.size();
}

下面是相同的在线https://gcc.godbolt.org/z/sb9b5E

以下是错误消息:

代码语言:javascript
复制
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                           
> $ g++ -O1 main.cpp                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                             
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                          
> $ g++ -O2 main.cpp                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                             
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                         
> $ g++ -O3 main.cpp                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                             
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                           
> $ g++ -O4 main.cpp                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                             
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                            
> $ g++ -O0 main.cpp                                                                                                                                                                                                                                                                        
/tmp/cc8D7sNK.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0x1c0): undefined reference to `B::ID'
collect2: error: ld returned 1 exit status
                                                                                                                                                                                                                                                                                             
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                            
> $ clang++ -O0 main.cpp                                                                                                                                                                                                                                                                    
/tmp/main-c49b32.o: In function `__cxx_global_var_init.1':
main.cpp:(.text.startup+0x7a): undefined reference to `B::ID'
clang-8: error: linker command failed with exit code 1 (use -v to see invocation)
                                                                                                                                                                                                                                                                                             
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                           
> $ clang++ -O1 main.cpp                                                                                                                                                                                                                                                                    
/tmp/main-cf18ee.o: In function `__cxx_global_var_init.1':
main.cpp:(.text.startup+0x3c): undefined reference to `B::ID'
clang-8: error: linker command failed with exit code 1 (use -v to see invocation)
                                                                                                                                                                                                                                                                                             
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                            
> $ clang++ -O2 main.cpp                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                             
fld@flap ~/work/p/test1                                                                                                                                                                                                                                                           
> $ clang++ -O3 main.cpp                                                                                                                                                                                                                                                                    

如果有人对原因有任何想法,任何暗示都是受欢迎的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-29 14:11:10

您没有提供B::ID的定义。在优化程度较高的情况下,所有的访问都会被编译器删除。

您需要在toplevel作用域添加静态成员的定义:

代码语言:javascript
复制
const id_type B::ID;

如果只读取静态const数据成员,则不需要单独的定义,因为编译时间常数不被视为ODR使用(一种定义规则)。您需要定义的根本原因是,映射构造函数期望初始化程序列表中的std::map::value_type,即std::pair<const Key, T>。在本例中选择的构造函数是pair( const T1& x, const T2& y );,以便调用此构造函数--获取A::ID的地址,即B::ID,这构成了一个ODR--即使对于常量也是这样。

因为在这种情况下,这对构造函数几乎是微不足道的,所以在更高的优化中它会被内联,而对&B::ID的唯一引用消失了,因为B::ID的值是已知的,并且可以直接初始化这对。

另见:静态

如果您使用的是C++17或更新版本,也可以使用B:ID constexpr而不是const,那么您不需要单独的定义,因为constexpr是隐式inline (inline static const也应该是OK的)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63155276

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档