我有一个用C++编写的服务器应用程序.启动后,它在x86 Linux上使用大约480 KB的内存(Ubuntu 8.04,GCC 4.2.4).我认为480 KB是一个过多的内存:服务器甚至没有做任何事情,没有客户端连接到服务器.(另请参阅下面的评论,其中我解释了为什么我认为480 KB是大量内存.)服务器在初始化期间唯一做的事情就是产生一个或两个线程,设置几个套接字,以及其他简单的东西.非常记忆密集.
请注意,我在谈论实际内存使用情况,而不是VM大小.我通过在空闲笔记本电脑上启动我的服务器的100个实例来测量它,并在启动服务器实例之前和之后用"免费"测量系统内存使用情况.我已经考虑了文件系统缓存和类似的东西.
经过一些测试后,看起来C++运行时中的某些东西会导致我的服务器使用这么多内存,即使服务器本身没有做任何事情.例如,如果我插入
getchar(); return 0;
Run Code Online (Sandbox Code Playgroud)
之后
int main(int argc, char *argv[]) {
Run Code Online (Sandbox Code Playgroud)
然后每个实例的内存使用量仍为410 KB!
我的应用程序仅依赖于Curl和Boost.我有很多C编程经验,我知道C库在使用之前不会增加内存消耗.
我发现的其他事情:
我的结论如下:
我记得几年前关于C++动态链接器问题的一些KDE讨论.之后的Linux C++动态链接器导致KDE C++应用程序启动时间慢,内存消耗大.据我所知,这些问题已在C++运行时修复.但类似的东西可能是我所看到的过度记忆消耗的原因吗?
来自gcc /动态链接专家的答案非常感谢.
对于那些好奇的人,有问题的服务器是Phusion Passenger的日志记录代理:https://github.com/FooBarWidget/passenger/blob/master/ext/common/LoggingAgent/Main.cpp
我有一个ELF目标文件.我想知道它包含哪种类型的调试信息.它是用PPC架构的Diab编译器(C源代码)编译的.我很确定它是用调试符号构建的.
我试过提取调试信息,dwarfdump但我不工作,所以我猜调试信息不是DWARF类型.
$ dwarfdump file.elf
No DWARF information present in file.elf
Run Code Online (Sandbox Code Playgroud)
使用objdump显示调试信息是空的.
$ objdump -g file.elf
file.elf: file format elf32-powerpc
Run Code Online (Sandbox Code Playgroud)
可能是这个ELF文件不包含调试信息,即使ELF文件中有调用的部分.debug_sfnames,.debug_srcinfo并且.debug.srcinfo?或者调试信息是以objdump无法处理的格式存储的?
我已经看到使用gcc __section__属性(特别是在Linux内核中)将数据(通常是函数指针)收集到自定义ELF部分中.如何检索和使用这些自定义部分中的"东西"?
是否可以在UNIX上运行COFF可执行文件或在Windows上运行ELF可执行文件?在Windows和UNIX上运行任一文件类型的步骤是什么?我只是好奇.
如果没有挖掘GDB源代码,我在哪里可以找到有关用于创建核心文件的格式的文档?
在ELF规范离开核心文件格式打开,所以我想这应该是GDB规范的一部分!遗憾的是,我没有从GNU的gdb文档中找到任何帮助.
这就是我要做的事情:将虚拟地址映射到包含正在运行的进程的可执行文件/库中的函数名称.为此,我首先要从核心文件中找出从虚拟地址空间到可执行文件/库的名称的映射,然后深入到相关文件中以获取符号信息.
现在'readelf -a core'告诉我核心文件中的几乎所有段都是'load'类型 - 我猜这些是来自所有参与文件的.text和.bss/.data段,加上堆栈段.除了这些加载段,有一个音符段,但似乎不包含地图.那么关于哪个文件段对应的信息如何存储在核心文件中?这些"加载"段是否以特定方式格式化以包含文件信息?
我最近使用gcc在Debian Linux下编译了一个简单的hello world C程序:
gcc -mtune=native -march=native -m32 -s -Wunused -O2 -o hello hello.c
Run Code Online (Sandbox Code Playgroud)
文件大小为2980字节.我在十六进制编辑器中打开它,我看到以下几行:
GCC: (Debian 4.4.5-8) 4.4.5 GCC: (Debian 4.4.5-10) 4.4.5 .shstrtab .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .text .fini .rodata .eh_frame .ctors .dtors .jcr .dynamic .got .got.plt data.data .bss .comment
Run Code Online (Sandbox Code Playgroud)
他们真的需要吗?无法减少可执行文件的大小?
我有一个使用一堆.so文件的二进制文件.
bash-3.00$ file foo
foo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.21, dynamically linked (uses shared libs), not stripped
Run Code Online (Sandbox Code Playgroud)
但是如果我在这个文件上运行ldd,它就无法获取二进制文件所依赖的.so文件.
bash-3.00$ ldd foo
not a dynamic executable
bash-3.00$
Run Code Online (Sandbox Code Playgroud)
readelf确实显示了二进制文件使用的共享库列表.
bash-3.00$ readelf -d foo
Dynamic segment at offset 0x17c810 contains 70 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libdl.so.2]
Run Code Online (Sandbox Code Playgroud)
在这种情况下,为什么ldd无法获取库依赖项?
通过查看问题标题不要误解我 - 我知道它们是什么(可移植可执行文件的格式).但我的兴趣范围略有不同
我的困惑
我参与了重新托管/重新定位最初来自第三方的应用程序.问题是,有时目标代码的格式也是.elf,.COFF格式,仍然说"可执行和可链接".
我主要是Windows用户,并且知道在编译和汇编C/C++代码时,会得到类似于.o或.obj的东西.这是不可执行的(好吧,我从来没有尝试过执行它们).但是,当您完成链接静态和动态库并完成构建时,将显示可执行文件.我的理解是,您可以继续并链接该可执行文件,或者在必要时使用某种形式的脚本"bash"测试它.
但是,在Linux(或类UNIX系统)中,在编译和汇编C/C++代码之后会有.o文件.一旦链接完成,可执行文件就是a.out格式(至少在Linux的Ubuntu发行版中).在其他一些分销商中很可能是.elf.在我的快速网络搜索中,没有任何消息来源提到任何关于.o文件作为可执行文件.
质询
因此我的问题变成了以下几点:
可移植可执行文件和目标代码的真正定义是什么?
Windows和UNIX平台如何涵盖相同文件格式(.COFF,.elf)下的可执行文件和目标代码.
我误解了"可链接"吗?我对"可链接"的解释是编译目标代码,然后可以"链接"到其他静态/动态链接库.这是一个愚蠢的想法吗?
根据问题1.(可能还有2个)我是否需要使用符号表(例如.LUM或.MAP文件)和目标代码?调试符号中的符号,并在重新托管不同计算机上的可执行文件/目标文件时使用它们.
在此先感谢正确的推动.同时,如有必要,我会继续挖掘和更新问题.
UPDATE
我已经设法从某个地方挖出这个 :(似乎很多东西要吞下我.
Q1 ELF中程序头和节头之间有什么区别
Q1.1段和段之间有什么区别?
我相信pheaders只指向部分.
Q2.什么是文件头和程序头之间的差异
根据gnu ld链接器脚本,使用Id:GNU链接器:
PHDRS
{
name type [ FILEHDR ] [ PHDRS ] [ AT ( address ) ]
[ FLAGS ( flags ) ] ;
}
Run Code Online (Sandbox Code Playgroud)
您可以在程序标题类型后面使用FILEHDR和PHDRS关键字来进一步描述该段的内容.FILEHDR关键字表示该段应包含ELF文件头.PHDRS关键字表示该段应包含ELF程序头本身
This is a bit confusing
Run Code Online (Sandbox Code Playgroud)