最短的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程序,还是会导致段错误的主要内容,如果未能解决你的问题,请参考以下文章
Numpy C API - 使用 PyArray_Descr 创建数组会导致段错误