如何迫使档案器(AR)产生与对象文件相同的档案



我使用相当涉及的方法使用"目录"方法对象分配。该代码生成一个由基本指针填充的目录对象(全局静态映射),该指针指向派生对象。这都是亵渎神灵,但不是这里的重点。执行程序后,目录由所有派生对象填充,我们可以分配使用目录注册的任何内容,而无需维护候选派生类的列表。伟大的。但是,当一个派生的类之一通过Archiver(AR)运行,并且将存档用于链接器的对象文件时,代码会失败。有人可以告诉我为什么会发生这种情况吗?示例代码:

//Base.h
#include<unordered_map>
#include<string>
#include<map>
#include<iostream>
#include<memory>
class Base
{
public:
  Base( std::string name ):m_name(name){}
  virtual ~Base() {}
  std::string m_name;
};
class ObjectCatalogueEntryBase
{
public:
  typedef std::map< std::string, ObjectCatalogueEntryBase* > CatalogueType;
  ObjectCatalogueEntryBase(){}
  virtual std::unique_ptr<Base> Allocate( std::string const & ) = 0;
  virtual ~ObjectCatalogueEntryBase(){}
  static CatalogueType& GetCatalogue()
  {
    static CatalogueType catalogue;
    return catalogue;
  }
  static std::unique_ptr<Base> Factory( const std::string& objectTypeName, std::string const & name )
  {
    std::cout<<"Creating solver of type: "<<objectTypeName<<" name "<<name<<std::endl;
    ObjectCatalogueEntryBase* const  entry = GetCatalogue().at(objectTypeName);
    return entry->Allocate(name);
  }
};

template< typename TYPE >
class ObjectCatalogueEntry : public ObjectCatalogueEntryBase
{
public:
  ObjectCatalogueEntry():
    ObjectCatalogueEntryBase()
  {
    std::string name = TYPE::CatalogueName();
    (ObjectCatalogueEntryBase::GetCatalogue())[name] = this;
    std::cout<<"Registered Solver: "<<name<<std::endl;
  }
  ~ObjectCatalogueEntry() final{}
  virtual std::unique_ptr<Base> Allocate( std::string const & name) final
  {
    return std::unique_ptr<Base>(new TYPE(name));
  }
};
/// Compiler directive to simplify autoregistration
#define REGISTER_FACTORY( ClassName) namespace{ ObjectCatalogueEntry<ClassName> reg_; }

下一个文件:

// Derived.h
#include "Base.h"
class Derived : public Base
{
public:
  Derived( std::string name );
  ~Derived();
  static std::string CatalogueName() {return "Derived";}
};

下一个文件:

// Derived.cpp
#include "Derived.h"
Derived::Derived( std::string name):Base(name)
{}
Derived::~Derived()
{}
REGISTER_FACTORY(Derived)

下一个文件:

// main.cpp
#include "Derived.h"
int main()
{
  std::string newName("Foo");
  auto solver = ObjectCatalogueEntryBase::Factory(Derived::CatalogueName(),newName);
  return 0;
}

和makefile:

CPP=g++-mp-6
test: main.o Derived.o
    ${CPP} -std=c++14 -o test    main.o Derived.o
testlib: main.o Derived.a
    ${CPP} -std=c++14 -o testlib main.o Derived.a
main.o: main.cpp Base.h Derived.h
    ${CPP} -std=c++14 -c main.cpp 
Derived.o: Derived.cpp Derived.h
    ${CPP} -std=c++14 -c Derived.cpp 
Derived.a:
    ar qcsv Derived.a  Derived.o
clean:
    rm *.o *.a test testlib
all: test testily

因此,链接了两个可执行文件。第一个(测试)与对象文件链接并产生"正确"结果:

$ ./test
Registered Solver: Derived
Creating solver of type: Derived name Foo

第二个(testlib)与派生的文件链接为derived.a,该文件仅使用derived.o使用" ar"创建。结果是:

./testlib 
Creating solver of type: Derived name Foo
terminate called after throwing an instance of 'std::out_of_range'
  what():  map::at
Abort trap: 6

显然在这里没有发生注册,并且地图为空。GCC6和Apple Clang7的结果相同。我怀疑它与全局静态映射有关,但对" AR"不足以知道它从对象文件中剥离的内容。所以有两个问题:

  1. 为什么存档版本失败?
  2. 如何生成一个从链接器角度出现与对象文件相同的存档文件?

问题不是存档器,而是链接器。链接器获取每个对象文件,以及档案中所需的内容。您的存档成员不能解决任何未解决的参考,因此不需要。

GNU链接器理解--whole-archive,这是您在这里打算的。

相关内容

  • 没有找到相关文章

最新更新