我试图理解C / C ++中的编译和链接过程。我知道源文件首先由编译器转换为目标文件。然后,链接器从目标文件生成库或可执行文件。
我想首先阅读目标文件中的信息。这是我为实验编写的程序。
func.h
#include <iostream>
void beautifulprint(char *str);
func.cpp
#include "stdafx.h"
#include "func.h"
using namespace std;
void beautifulprint(char *str) {
cout << "*** " << str << " ***" << endl;
}
TestApp.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?链接器如何知道该函数存在于目标文件中。
另外为什么debug obj版本有iostream的功能?这些obj不应该存在于某些标准库中吗?
编辑:我以十六进制格式直接在VS 2010中打开了func.obj版本。我在右侧(ASCII)列搜索了beautifulprint及其现在。这意味着存在参考。为什么dumpbin没有显示出来?我需要一些工具以人类可读的格式查看它。
答案 0 :(得分:21)
转储符号。所有.obj文件都有一个符号表。它将向您显示内部定义的符号以及需要解析的符号。您看到的IO符号可能是UNDEF符号,但符号表应该更清晰。
DUMPBIN /SYMBOLS func.obj
请记住,使用/ GL(whole program optimization)编译对象时,/ SYMBOLS不可用。使用/ GL(以及库)创建的对象模块是使用不保证从一个编译器版本到下一个编译器版本兼容的格式创建的。
整个程序优化意味着优化器可以跨所有模块进行优化,而不是仅在每个模块中进行优化。功能可以变为“内联”,并且可能执行其他技巧,这些技巧可能与COFF不兼容。除非您为所有支持的编译器版本提供库,否则建议可交付库不设置/ GL选项。
答案 1 :(得分: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