【问题标题】:About pointers and segmentation fault关于指针和分段错误
【发布时间】:2020-09-30 16:38:04
【问题描述】:

所以,我有这个代码:

#include <stdio.h>

int main()
{
    char *p;
    int var = -1;
    int i;

    /* Printing all memory we can read */
    p = (char *)&var;
    /* No stopping condition. The OS will stop us */
    for (i = 0;; i++)
    {
        printf("(%i) %i\n", i, p[i]);
        /*
         * The next statement also tries to write a zero
         * starting from &var. Try to uncomment and explain ...
         */
        //p[i] = 0;
    }
}

以这种方式,它会出现应有的分段错误,输出:

..................
(6556) 108
(6557) 116
..................
(6582) 0
(6583) 0
Segmentation fault

取消注释上面的这行代码:p[i] = 0;

它不会出现分段错误,输出是这样的:

..........
(1) 0
(2) 0
(3) 0
(4) 4
(1) 0
(2) 0
(3) 0
(4) 4
(1) 0
(2) 0
(3) 0
(4) 4
(1) 0
^C
i have to interrupt it

不明白为什么会这样,而且看起来 i 没有增加

【问题讨论】:

  • 这是未定义的行为,您无法对其进行可靠的推理。您可以在调试器汇编模式下运行这两个代码,并准确查看在您的特定情况下发生了什么。不过,这并不是一个非常有见地的课程。
  • 虽然这确实是未定义的行为,但“幕后”发生的事情很可能是通过将零写入内存而不允许您覆盖 i 和/或 @ 的值987654326@.

标签: c pointers segmentation-fault


【解决方案1】:

这样,它应该会出现分段错误

并不是“应该”做任何特定的事情。当i &gt;= sizeof(int)未定义的行为时,你对p[i] 所做的事情,真的有可能发生。

在上面取消注释这行代码:p[i] = 0; 它不会进入分段错误

它仍然是未定义的行为。它不会导致分段错误这一事实并不意味着什么。我只能猜测的是,p[i] = 0 在某些时候最终会用0 覆盖i 的值,因此你最终会陷入无限循环。

不明白为什么会这样

试图理解未定义的行为没有多大意义。没有合理的解释,只能猜测。


如果您想讨论给定程序的特定编译器生成的程序集,那么我们可以讨论它并告诉您确切的原因,但是鉴于您的 C 源代码,任何事情都可能发生。未定义的行为就是未定义的行为。

【讨论】:

  • i 根本不必在内存(堆栈)中。所以建议写i的解释不太可能
  • @P__J__ 没有优化的 GCC 可以(并且将)很好地将 i 放在堆栈上,并在每次迭代时将其移动到寄存器中(example),所以是的,我会说我是非常有信心这就是 OP 的代码所发生的事情。
  • godbolt.org/z/Yn8nc5 即使您更改了声明的顺序,也只有 icc 会这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-02
  • 2013-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多