【问题标题】:C corner case and trapC 角盒和陷阱
【发布时间】:2010-09-01 13:03:10
【问题描述】:

我很惊讶为什么会这样?

short main [] ={};

这是文件中唯一的内容。它在 gcc 上正确编译。但是当我运行它时会打印分段错误。当我重命名 main 时,编译器会出错。 谁能解释一下这里发生了什么。

【问题讨论】:

  • 我确定我已经看过这个了,你声明了一个外部符号 main 并且链接器不关心类型。这是不正确的 C.
  • -1 用于询问为什么一些具有未定义行为的荒谬代码“有效”(在非常反常的意义上更糟,不少于)。
  • 我想有人应该提到这个IOCCC entry
  • 在什么情况下给出分段错误算作有效?
  • 我的问题是为什么编译时没有 main 函数。

标签: c platform-specific


【解决方案1】:

显然链接器不知道全局对象的类型(例如:变量或函数),而只知道地址;所以它链接程序,就好像你的变量是一个函数一样。由于明显的原因而崩溃。

【讨论】:

    【解决方案2】:

    你会遇到这样的错误吗?

    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[] = {};
    

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

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

    结果是程序虽然写错了,但生成没有错误。

    程序运行时,所谓的main不保存可执行代码。相反,它只是一些数据(可能归零)。所以系统可能会做任何意想不到的事情(在你的情况下,它是一个 SEGFAULT)。

    这实际上可以在使用 gcc 中的 -Wall 标志进行编译时被捕获,这会给出警告:

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

    【讨论】:

    • 好的,我明白了,但我又想到了一个问题,我们能不能在这个数组中写一些有用的东西,比如打印你好。有一个gcc选项fwritablestrings,它会做什么?
    • 短主[] = {};我不认为这是有效的声明。零初始化?也许是有效的 C99?
    • @Nyan:也许是 GCC 扩展。无论如何,这不是重点。
    【解决方案3】:

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

    例如添加简单的-Wall

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

    我还没有阅读相关的标准页面,但显然你只需要拥有某种 main 才能编译,不一定是函数......

    【讨论】:

    • gcc -ansi -pedantic -W -Wall
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多