【问题标题】:what makes difference with these two programs in C这两个程序在 C 中有何不同
【发布时间】:2011-10-10 14:12:24
【问题描述】:

我有两个非常相似的程序,如下。

程序A:运行时没问题,

#include <string.h>
#include <stdio.h>

typedef struct p_struct{
   unsigned char* pulist;
   int length;
} list_type;

int get_struct(list_type* l)
{
   memset(l->pulist, 0, 4); 
   l->length=4;
}

int main ()
{
   list_type str;
   get_struct(&str);
}

程序 B:有一个额外的函数调用,仍然可以编译,但由于 gcc 的运行时错误“分段错误”而崩溃。

#include <string.h>
#include <stdio.h>

typedef struct p_struct{
   unsigned char* pulist;
   int length;
} list_type;

int get_struct(list_type* l)
{
   memset(l->pulist, 0, 4); 
   l->length = 4;
}

int get_struct_a()
{
   list_type str;
   get_struct(&str);
}

int main ()
{
   get_struct_a();
}

我真的很难找出这里的问题。谁能告诉我是什么导致“分段错误”?另外,为什么程序 B 给出“分段错误”错误,而程序 A 没有?

【问题讨论】:

  • 他老派又没用,typedef struct 构造怎么了?
  • @John Dibling:这是 C,而不是 C++,它是定义类型的一种完全有效且有用的方法。
  • 它最初被标记为 C++。

标签: c function pointers segmentation-fault


【解决方案1】:

您没有为结构的pulist 成员分配内存。因此,当您 memset 它时,您正在其他地方覆盖一些其他内存。幸运的是,在第二种情况下,您覆盖的内存碰巧没有给出段错误,但您仍在破坏内存。

【讨论】:

  • 偶然?我知道了。但这个机会似乎太高了。
  • @pepero 显然不是太高,因为这就是正在发生的事情。
  • 我不确定你的意思;在这两个可执行文件中,pulist 的位置将是固定的,但在这两种情况下是不同的。一个给你一个段错误,一个没有。
  • 谢谢 Vicky 和其他人。一开始,我以为是因为没有给定“指针”,或者没有分配内存,并且我预计A中会发生同样的“Seg错误”。但是,我没有看到A中的错误,我开始怀疑自己.
  • @pepero, pulist 存在,但它是一个未初始化的指针,然后传递给memset()。崩溃总比看似偶然工作要好。至少这次崩溃让问题变得显而易见。
【解决方案2】:
memset(l->pulist, 0, 14);

可能是它崩溃的原因。在尝试将 l-&gt;pulist 用作指向某个内存的指针之前,您没有为它分配任何内存。

这个

memset(l->pulist, 0, 4); 

也应该崩溃,但它的工作是偶然的。

发生的事情是您正在堆栈上分配其中一个structs,并且所有成员中都有一些随机垃圾值(恰好在分配的内存中的值)。然后,您尝试将这些随机值之一用作指针,并告诉memset,“用 0 覆盖此随机位置的 14 个字节。”您可以看到为什么会导致问题。但由于指针是随机的,它并不总是造成问题。

你需要做类似的事情

l->pulist = malloc(size);

在类似操作中使用它之前使其成为有效指针。

【讨论】:

    【解决方案3】:

    你永远不会将pulist 初始化为任何东西,所以它只是指向任何地方。它在一种情况下崩溃,但在另一种情况下不会崩溃,这纯属巧合。

    【讨论】:

      【解决方案4】:

      当程序尝试访问不允许访问的内存位置,或尝试以不允许的方式访问内存位置(例如,尝试写入只读位置,或覆盖部分操作系统)。

      分段错误的几个原因可以总结如下:

      • 试图执行无法正确编译的程序。请注意,如果出现编译时错误,大多数编译器不会输出二进制文件。

      • 缓冲区溢出。
      • 使用未初始化的指针。
      • 取消引用 NULL 指针。
      • 试图访问不属于该程序的内存。
      • 试图更改程序不拥有的内存(存储违规)。
      • 超出允许的堆栈大小(可能是由于递归失控或无限循环)

      通常,发生分段错误的原因是:指针为 NULL,指向随机内存(可能从未初始化为任何内容),或指向已释放/解除分配/“删除”的内存。

      【讨论】:

        【解决方案5】:

        我会说结构成员 pulist 是一个未初始化的指针。在你使用 memset 之前,你需要为这个成员分配一些内存。

        【讨论】:

          【解决方案6】:

          您还没有初始化您的pulist 成员以指向任何有意义的地方;它只包含一个随机位串。在程序 A 中,该随机位串对应于恰好可写的内存地址。在程序 B 中,它没有。

          这两个程序都同样错误。创建list_type 对象时,您需要显式设置pulist 成员以指向您拥有的缓冲区。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-07-05
            • 2023-04-02
            • 1970-01-01
            • 1970-01-01
            • 2019-09-09
            • 2021-10-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多