【问题标题】:Can anyone explain to me what actually causes this Segmentation Fault and How to overcome this?谁能向我解释究竟是什么导致了这个分段错误以及如何克服这个问题?
【发布时间】:2019-07-27 07:35:36
【问题描述】:
#include <stdio.h>

#define null1 ((void*)0)
#define val ((int)2)

int main() {
    int *p;
    p = null1;
    printf("%p", &p);
    //p = (int *)val;
    *p = val;
    //printf("\n%p", (int*)p);
    return 0;
}

输出:

Segmentation fault(core dumped)

我想给指针赋值宏。

【问题讨论】:

  • p 被初始化为一个空指针(被你对宏的使用稍微伪装了)。评估 *p 具有未定义的行为。语句*p = val 都评估*p 以获得地址,并将该地址分配给2 的值,这会覆盖程序不应访问的内存。主机系统检测到这一点,并向您的程序发送一个信号,这会导致程序终止并显示有关分段错误的消息。一种可能的解决方法 - 创建一个 int 并分配 p 的地址,例如int i; p = &amp;i; 在第一个 printf() 之前
  • 不清楚你不想做什么。你是想让p 指向某个保存值2 的地方,还是要强制p 保存一个整数,而不是一个指针?
  • @eddyctid:您可以通过点击分数下方的灰色复选标记来接受其中一个答案。

标签: c pointers segmentation-fault null-pointer


【解决方案1】:

null1 是一个空指针,它的定义#define null1 ((void*)0) 是空指针的公认定义之一。

val 是一个扩展为普通整数常量2 的宏。将2 转换为(int) 无效,2 已经是int 常量值。

将值存储到空指针具有未定义的行为。分段错误是未定义行为的可能影响之一。一个相当有用的方法,因为它允许调试器立即指出问题。

将任何其他整数值转换为 (int *) 也有未定义的行为:p = (int *)val; *p = val; 很可能会导致相同的分段错误,但可能会产生一些其他意想不到的副作用,具体取决于目标平台的具体情况:如果 2正好是自毁触发端口的地址,赌输了。

【讨论】:

    【解决方案2】:

    空指针是指针的特殊保留值。任何类型的指针都有这样的保留值。形式上,每种特定的指针类型(int *、char * 等)都有自己专用的空指针值。从概念上讲,当指针具有空值时,它不会指向任何地方。

    void 指针是一种特定的指针类型 - void * - 指向存储中某个数据位置的指针,它没有任何特定类型。

    这里的 null1 指的是一个 void 指针,而 p 是一个整数类型的指针。

    希望我是对的,这对你有帮助。

    【讨论】:

      【解决方案3】:

      指针直接指向内存地址。虽然我们运行的每个程序都只分配了一个固定的内存区域(称为段)。该区域的所有内存地址都使用相对内存地址来引用。

      但是指针中有绝对的内存地址。通常,起始内存地址是供操作系统使用的。当您将指针分配给其段区域之外的某个地址时,它会给出 SIGSEGV (分段错误)。

      在您的情况下,您也试图在其段区域之外为 p 分配一个地址,因此出现错误。

      【讨论】:

        【解决方案4】:

        NULL指针是一个无效指针,因为它指向的内存是不能访问的,所以语句*p = val是无效的,所以出现Segmentation fault错误。

        要克服此错误,您需要将内存位置的有效地址分配给指针 (p),例如定义变量 (var) 并将地址分配给指针为 p = &amp;var;。

        【讨论】:

        • 鉴于val的定义,p = &amp;val;也将无效。
        • @chqrlie 我只是注意到 val 是宏而不是变量。我编辑了我的答案。谢谢:)。
        【解决方案5】:

        您只需将指针分配给您的宏,如下代码:

        #include <stdio.h>
        
        #define val 2
        
        int main()
        {
            int *p;
        
            p = (int*)val;
            printf("%p\n", &p);
            printf("%d\n", p);
        
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 2016-05-18
          • 1970-01-01
          • 2021-01-08
          • 1970-01-01
          • 2012-09-21
          • 2022-11-10
          • 2013-04-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多