最短的C程序,还是会导致段错误

Posted

技术标签:

【中文标题】最短的C程序,还是会导致段错误【英文标题】:The shortest C program, still causes segfault 【发布时间】:2013-02-26 07:30:04 【问题描述】:

有那么一刻,我为自己编写了我的第一个可能没有错误的 C 程序感到非常自豪。 这是完整的源代码:

int main;

即使没有int,它也能完美编译,但会发出警告(即使没有-Wall),作为一个以无错误程序为目标的程序员,我将它们视为错误。

愉快地编译了这个应用程序后,我立刻赶忙启动它。令我惊讶的是,出现了分段错误错误...


现在说真的。 到底发生了什么?

我的猜测如下:是缺少main的定义。这很明显,但编译器允许这样做。好的,main 可以在不同的单元中定义。但即使是链接器也没有做任何事情。有什么特别的原因吗?

【问题讨论】:

我认为问题在于你只定义了原型而不是函数本身,但是等等:你只定义了一个变量而没有函数。到目前为止,入口点还没有定义。 这个explanation on Reddit 可能会有所帮助。 这取决于您编译程序的方式和位置。托管环境程序需要main,但独立环境程序不需要。 关于警告:gcc -Wall -g -o main main.c 给我main.c:1: warning: ‘main’ is usually a function(使用gcc (Debian 4.4.5-8) 4.4.5)。 @DCoder 您(或原始发帖人)可能应该引用链接的解释作为这个问题的答案。 【参考方案1】:

单词main 是任何变量的合法名称。典型的用例是向编译器提供一个名为 main 的函数,编译器将其编译为一个目标文件,该目标文件又与为运行时提供初始化(堆栈分配等)的 crt0.o 链接到并跳转到标签main

在 C 目标文件中,符号与原型无关,链接器成功链接全局变量 int main; 作为要跳转到的主程序。然而,这个程序是垃圾。它很可能初始化为零,但很快处理器会遇到随机指令访问程序分配的数据空间(堆栈 + 堆)之外的内存,或者指令流达到保留代码空间的限制。

两者都会导致分段错误。实际上,如果系统在具有 eXecution 标志 的体系结构上运行,则程序在第一次尝试跳转到 data 段或页面时会出现段错误,而没有执行权限。

进一步阅读以支持 cmets 中的讨论:Data Execute Prevention、NX_bit

【讨论】:

我想在 MS-DOS 时代,可以写一个工作的char main=0xc3; 试试const char main=0xc3; 对,甚至const main=195; 适用于 x64 Ubuntu。关键是 const 数组/字符串在 .text 段中编译,以便使用 mov label[%rip], %rax 范式达到顺序,这是 x64 中加载 64 位常量的最短机器代码序列。 很好的答案。我只希望通过一些参考来完成它(例如关于数据执行预防)。只是为了完整性。 reddit 线程可能很有用。

以上是关于最短的C程序,还是会导致段错误的主要内容,如果未能解决你的问题,请参考以下文章

段错误的最小 C/C++ 程序? [复制]

Numpy C API - 使用 PyArray_Descr 创建数组会导致段错误

尝试访问时带有结构的 C mq_receive() 会导致段错误

释放时填充结构数据会导致段错误

在c ++中执行后出现“段错误”错误[关闭]

为啥无限递归会导致段错误