20

我试图了解 C/C++ 中的编译和链接过程。我知道源文件首先由编译器转换为目标文件。然后链接器从目标文件生成库或可执行文件。

我试图首先阅读目标文件中的信息。这是我为实验编写的程序。

函数.h

#include <iostream>

void beautifulprint(char *str);

函数cpp

#include "stdafx.h"
#include "func.h"

using namespace std;

void beautifulprint(char *str) {
    cout << "*** " << str << " ***" << endl;
}

测试应用程序.cpp

#include "stdafx.h"
#include "func.h"

int _tmain(int argc, _TCHAR* argv[])
{
    beautifulprint("Hello, world!");

    return 0;
}

在 VS 2010 中构建项目后,我得到了 func.obj。我假设在 func.obj 中的某个地方应该有 beautifulprint 函数的引用。我为 func.obj 的调试和发布版本运行了以下内容

dumpbin /HEADERS func.obj > funchead.txt

下面是输出。

调试版本(不包括完整输出,因为它非常大)

...

SECTION HEADER #41
   .text name
       0 physical address
       0 virtual address
      78 size of raw data
    5B94 file pointer to raw data (00005B94 to 00005C0B)
    5C0C file pointer to relocation table
       0 file pointer to line numbers
       A number of relocations
       0 number of line numbers
60501020 flags
         Code
         COMDAT; sym= "void __cdecl beautifulprint(char *)" (?beautifulprint@@YAXPAD@Z)
         16 byte align
         Execute Read

SECTION HEADER #42
.debug$S name
       0 physical address
       0 virtual address
      E8 size of raw data
    5C70 file pointer to raw data (00005C70 to 00005D57)
    5D58 file pointer to relocation table
       0 file pointer to line numbers
       7 number of relocations
       0 number of line numbers
42101040 flags
         Initialized Data
         COMDAT (no symbol)
         Discardable
         1 byte align
         Read Only

...

发布版本(完整输出!)

Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file func.obj

File Type: ANONYMOUS OBJECT

ANON OBJECT HEADER VALUES
               1 version
             14C machine (x86)
        50213733 time date stamp Tue Aug 07 16:41:39 2012
                 ClassID: {0CB3FE38-D9A5-4DAB-AC9B-D6B6222653C2}
             2D1 size
               0 flags

这是我的问题。不出所料,func.obj Debug 版本有对 beautifulprint 的引用。但令我惊讶的是,Release 版本中没有提到 beautifulprint?链接器如何知道此函数存在于目标文件中。

另外为什么调试 obj 版本具有来自 iostream 的功能?这些不应该出现在某个标准库而不是这个obj中吗?

编辑:我直接在 VS 2010 中以 Hex 格式打开了 release func.obj。我在右侧 (ASCII) 列中搜索了 beautifulprint 及其存在。这意味着引用存在。为什么垃圾箱不显示它?我需要一些工具来以人类可读的格式查看它。

4

2 回答 2

25

转储符号。所有 .obj 文件都有一个符号表。它将向您显示内部定义的那些符号,以及那些需要解析的符号。您看到的 IO 符号可能是 UNDEF 符号,但符号表应该更清楚。

DUMPBIN /SYMBOLS func.obj

请记住,当使用 /GL(整个程序优化)编译对象时,/SYMBOLS 不可用。使用 /GL 创建的对象模块(以及库)是用一种不保证从一个编译器版本到下一个编译器版本兼容的格式创建的。

整个程序优化意味着优化器可以跨所有模块进行优化,而不是仅在每个模块内进行优化。函数可以成为“内联”和其他可能与 COFF 不太兼容的技巧。除非您为所有受支持的编译器版本提供库,否则建议可交付库不要设置 /GL 选项。

于 2012-08-07T16:15:35.697 回答
1

我使用了objdump(在 gnu c,windows 平台中)。

    C:\...obj>objdump -t winsock001.o
         
    winsock001.o:     file format pe-x86-64
    SYMBOL TABLE:
    [  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x0000000000000000 winsock001.c
__main
__imp_WSAStartup
__imp_socket
__imp_htons
__imp_inet_addr
__imp_connect
__imp_closesocket
__imp_WSACleanup
__imp_WSAGetLastError
printf
puts
于 2021-02-11T17:29:16.960 回答