2010-09-01 59 views
3

我很惊讶,为什么这个工程?C角箱和陷阱

short main [] ={}; 

这是文件中唯一的内容。它在gcc上正确编译。但是,当我运行它打印分段错误。当我重命名主,编译器给出错误。 任何人都可以解释我在这里发生了什么。

+0

我相信,我已经看到了这一个已经,您声明外部符号主要和连接器没有按不关心类型。这是不正确的C. – jbcreix 2010-09-01 13:06:28

+1

-1对于问题为什么一些有未定义行为的荒谬代码“起作用”(在一个非常不好的意义上,不会更少)。 – 2010-09-01 13:18:05

+2

我想有人应该提到这个[IOCCC entry](http://www.ioccc.org/years.html#1984_mullender)。 – 2010-09-01 13:30:44

回答

4

显然,链接器不知道全局对象的类型(如:变量或函数),但只有地址;所以它将程序链接起来,就好像你的变量是一个函数一样。出于显而易见的原因,这崩溃了。

1

尝试使用更多选项编译。 :)

例如添加简单-Wall

gcc -Wall test.c -o t 
test.c:1: warning: ‘main’ is usually a function 

我没有看到相关的标准页,但显然你就必须有主某种以编译,不一定是功能.. 。

+0

'gcc -ansi -pedantic -W -Wall' – 2010-09-01 13:16:23

3

你是否得到这样的错误?

Undefined symbols: 
    "_main", referenced from: 
     start in crt1.10.6.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 

这不是编译器错误,而是链接器错误。

在编译时,每个源文件都被转换为一个目标文件。

没有检查是否存在int main(),因为该程序可能由多个来源组成,并且main()仅在其中一个中定义,或者甚至不需要存在(例如在动态库中)。由于源

short main[] = {}; 

是由编译器视为一个有效的声明(创建一个全局short阵列命名为main并初始化为空数组),也不会产生任何错误。

连接器检查是否存在int main()存在。链接器将编译后的对象文件绑定到可执行文件。如果链接器找不到符号main,它会像我上面描述的那样抱怨。不幸的是,传统的C ABI没有区分函数或输出变量。所以,即使main被声明为一个数组,因为链接器只知道“存在一个叫main的东西”,并且不能检查更多,它也会通过。

结果是程序生成没有错误,虽然它被错误地写入。

程序运行时,所谓main不包含可执行代码。相反,它只是一些数据(可能为零)。所以系统可以做任何意想不到的事情(在你的情况下,它是一个SEGFAULT)。与-Wall标志GCC,这给出了一个警告,编译时

这实际上可以被捕获:

<stdin>:1: warning: ‘main’ is usually a function 
+0

好的,我明白了,但是我还有一个问题在我脑海里浮现,我们能否在这个阵列中写些东西来做一些有用的事情,比如打印你好。有一个gcc选项fwritablestrings,它会做什么? – 2010-09-01 15:00:41

+0

short main [] = {}; 我不认为这是有效的声明。零初始化器?也许有效的C99? – Nyan 2010-09-01 16:51:11

+0

@Nyan:也许GCC扩展。无论如何,这不是重点。 – kennytm 2010-09-01 17:16:58