这与C中的这两个程序有什么不同

时间:2011-10-10 14:12:24

标签: c function pointers segmentation-fault

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

程序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没有?

6 个答案:

答案 0 :(得分:5)

您没有为结构的pulist成员分配内存。因此,当你memset时,你会覆盖其他地方的其他内存。幸运的是,在第二种情况下,你覆盖的内存不会产生段错误,但你仍然在破坏内存。

答案 1 :(得分:3)

您永远不会将pulist初始化为任何内容,因此它指向任何地方。在一种情况下,它崩溃只是纯粹的巧合,而不是另一种情况。

答案 2 :(得分:3)

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

可能是什么崩溃了。在尝试将其用作指向某些内存的指针之前,您不会为l->pulist分配任何内存。

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

也应该崩溃,但这是偶然的。

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

您需要执行类似

的操作
l->pulist = malloc(size);

在使用它之前使其成为有效指针。

答案 3 :(得分:1)

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

分段错误的一些原因可归纳如下:

  • 尝试执行无法正确编译的程序。请注意,在给定编译时错误的情况下,大多数编译器都不会输出二进制文件。

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

通常,出现分段错误的原因是:指针为NULL,指向随机存储器(可能从未初始化为任何内容),或指向已释放/取消分配/&#34;删除的内存&#34;。

答案 4 :(得分:0)

我会说struct member pulist是一个未初始化的指针。因为你需要使用memset为这个成员分配一些内存。

答案 5 :(得分:0)

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

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