用clang无法转储C++对象的内存布局

4

我读了一篇关于使用Clang转储C++对象的内存布局的文章(译者注:原文链接被屏蔽),现在我正尝试使用这个功能进行实验。我创建了两个类:

// simple.cpp
struct Base
{
    int value;
};

struct Derived : Base
{
    int count;
};

int main(int argc, char* argv[])
{
    return 0;
}

并运行以下命令:

$ clang -cc1 -fdump-record-layouts-simple simple.cpp

什么都没有。clang 版本是:

$ clang++ -dumpversion
4.2.1

如果我运行以下命令:
$ clang -cc1 --help

在许多信息中,我可以找到这个:

...
  -fdump-record-layouts-simple
                          Dump record layout information in a simple form used for testing
  -fdump-record-layouts   Dump record layout information
  -fdump-vtable-layouts   Dump the layouts of all vtables that will be emitted in a translation unit
...

我做错了什么?

2个回答

5
你需要进行两个更改:
  1. 添加-emit-llvm编译器开关。如果不添加此开关,则不必要输出LLVM代码,因此记录的布局永远不会被计算也不会被转储。
  2. 在你的代码中使用类。如果没有使用类,则不会为其生成任何代码,并且它们的布局不会被转储。
做出这些更改后,标准输出将打印如下内容:
*** Dumping AST Record Layout
Type: struct Base

Layout: <ASTRecordLayout
  Size:32
  DataSize:32
  Alignment:32
  FieldOffsets: [0]>

*** Dumping AST Record Layout
Type: struct Derived

Layout: <ASTRecordLayout
  Size:64
  DataSize:64
  Alignment:32
  FieldOffsets: [32]>

...

Layout: <CGRecordLayout
  LLVMType:%struct.Base = type { i32 }
  NonVirtualBaseLLVMType:%struct.Base = type { i32 }
  IsZeroInitializable:1
  BitFields:[
]>

Layout: <CGRecordLayout
  LLVMType:%struct.Derived = type { %struct.Base, i32 }
  NonVirtualBaseLLVMType:%struct.Derived = type { %struct.Base, i32 }
  IsZeroInitializable:1
  BitFields:[
]>

5

根据我使用clang 10.0.1的经验,以下是更新:

  • 必要条件是编译器需要一些理由来关心所讨论的结构体的布局。因此,在原始问题中的simple.cpp源文件似乎从未导致转储。我发现添加代码来实例化其中一个结构体、调用sizeof(...),或调用它们的虚拟方法可以解决。

  • 如果您正在使用-cc1,则需要使用-emit-llvm 或者 -emit-obj 才能导致转储。(也许其他选项也可以工作,但在我的实验中,我至少需要其中一个。)

  • 如果您不想使用-cc1选项(可能是因为您想将这些选项添加到一个假设与g++兼容的现有构建系统中),那么像这样的调用也可以: clang -Xclang -fdump-record-layouts-simple simple.cpp。(采用这种方法的好处是,至少在我的系统上,以这种方式调用clang会使结构体布局信息在终端上呈现出彩色效果。)

  • 我上面写的东西似乎也适用于-fdump-record-layouts-fdump-vtable-layouts选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接