【问题标题】:Segmentation fault on time(0);分段错误准时(0);
【发布时间】:2010-12-16 10:49:58
【问题描述】:

我正在重写一个旧程序来做一些新的事情,突然我在下面的代码行中得到一个分段错误错误:

time_t seconds_since_time_begun = time(0);

为什么,哦,为什么?

更新:
我在我的代码中包含了 time.h 头文件,当我尝试下面的 pmg 建议时,两个变量的大小都是 4。

当我尝试以下操作时:

printf("4\n");
// time_t seconds_since_time_begun = time(0);
printf("5\n");

即使在调用 time() 的行被注释掉后,我仍然会在打印“4”后立即出现分段错误。不输出“5”。这怎么可能?

更新 2:
我一步一步地重建了我的函数,试图找出错误发生在我的代码中的位置,我想我找到了问题所在。我不确定出了什么问题,但它与整数数组值和 0 之间的比较有关。所以,我认为段错误不是由我对 time(0) 的调用引起的……但我是仍然不确定实际发生了什么。总之,问题解决了。谢谢各位。

【问题讨论】:

    标签: c macos time segmentation-fault time-t


    【解决方案1】:

    也许您的堆栈帧中有一个大得离谱的对象溢出堆栈?请参阅this blog post 了解如何发生这种情况的详细示例以及对情况的分析。 time(2) 函数允许将 NULL 传递给它,并且您的 time() 实现不太可能有错误。

    【讨论】:

      【解决方案2】:

      如果您有#include <time.h>,编译器知道它需要将0 转换为NULL 指针。否则,它会将int 传递给函数。

      我认为您的实现对待(int)0(time_t*)0 不同。

      所以...添加

      #include <time.h>
      

      到你的代码

      编辑

      试试这个

      #include <stdio.h>
      #include <time.h>
      
      int main(void) {
          printf("size of (int): %d\n", (int)sizeof (int));
          printf("size of (time_t*): %d\n", (int)sizeof (time_t*));
          return 0;
      }
      

      【讨论】:

      • 除非他的 C 编译器将NULL 定义为((void*)0),在这种情况下参数传递得很好。但返回类型可能不匹配(例如,time_tlong 而不是 int)。
      • NULL 是一个宏。仅当他 #include &lt;stddef.h&gt;(或大量其他标头)时才定义它。一个普通的0 需要被转换为一个 NULL 指针,但是编译器只会在原型存在的情况下这样做。
      • 如果 OP 使用的是具有 64 位指针和 32 位整数的系统并且不包括 &lt;time.h&gt;,那么 time() 将收到一个 8 字节的指针,其中只有 4 个字节为 0,其他 4 个字节为随机堆栈垃圾。 time() 会将此视为一个非空指针,尝试取消引用它,然后出现段错误。
      • 除了第一个整数/指针参数在 64 位 OS X 系统上的寄存器(具体来说是%rdi)中传递。由于移入寄存器,高半部分也将设置为零。
      • @Stephen Canon:很好,我忘记了 x86-64 调用约定在寄存器中传递前几个参数。这使得 OP 的问题更加神秘。
      【解决方案3】:

      您经常会发现在不正确的行上会捕获到分段错误。它周围的线条是什么?是否有可能是其中之一导致它?

      标准库的 time 函数以 time_t * 作为参数,对吧?因此,遇到段错误也就不足为奇了:您正在尝试取消引用 NULL 指针!

      time(0) 或 time(NULL) 是使用 time 函数访问当前时间的标准且公认的方式。

      See reference.

      【讨论】:

      • 也许你可以去组装看看这个问题到底发生在哪里
      【解决方案4】:

      您的程序是否可能包含名为time的变量或局部函数与标准库的time函数发生冲突?

      【讨论】:

      • 目前最好的猜测。
      • 你不会得到一个错误吗?我不认为(严格)C 允许你有这样的名称冲突
      • @earlz:自己试试;使用函数(比如)int time(int *t) { return *t; } 创建一个文件,然后创建另一个包含&lt;time.h&gt; 的文件,并使用time(0) 调用标准时间函数。使用您能看到的最严格的设置进行编译。这样做,我可以在没有警告的情况下编译代码,它确实会产生崩溃。
      • 我建议这样做是因为类似的事情发生在我们身上(几年前),一个名为 link 的全局变量与 Unix 库函数 link 发生冲突。
      【解决方案5】:

      正如 Adam Rosenfield 所指出的,当堆栈空间不足时,程序可能会在调用任何函数(不仅仅是系统调用)时出现段错误。

      现在,您的程序实际上可能确实需要在堆栈而不是堆上存储大量数据。在这种情况下,解决方案可能是更改特定环境的最大堆栈空间。

      在 Linux 上,可以使用ulimit 进行更改,例如

      ulimit -S unlimited
      

      【讨论】:

        【解决方案6】:

        很好,但您是否打算将空指针作为 time(time_t *t) 传递给它?

        time(NULL);
        time(((void*)0));
        

        不是零?

        【讨论】:

        • 你认为 NULL 会扩展成什么?
        • 是的.. 它被定义为扩展为 0(它是真的!)但是使用 0 代替 null 仍然是不好的编码
        • 其实最近的标准推荐使用0而不是NULL。
        • @Alcon 你能解释一下吗?链接到解释的东西?
        • 使用0 代替NULL 是邪恶的。
        猜你喜欢
        • 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
        相关资源
        最近更新 更多