2013-05-28 66 views
3

该程序在我的UNIX计算机上导致seg错误。我将原因缩小到调用memset()的调用memset导致分段错误

为什么会发生这种情况?第一个“代码块”与第二个代码块几乎相同,不是吗?为什么没有第一个调用memset段错误,如果第二个呢?

我查看了关于segfaulting memset调用的其他线程,但没有一个与此类似。

如果你想知道为什么我写了这样一个小程序,它是从我一直在写的另一个程序改编的,我用它来教自己如何将memcpy()应用到结构中。

#include <stdio.h> 
#include <stdlib.h> 

typedef struct{ 
    int x; 
    char text; 
} FilesStruct; 

int 
main(int argc, char** argv) 
{ 
    FilesStruct *old_dir; 
    memset(old_dir,0,sizeof(FilesStruct)); 
    old_dir->x = 3; 
    old_dir->text = 'c'; 
    printf("old dir: %d,%c\n",old_dir->x,old_dir->text); 

    FilesStruct *new_dir; 
    memset(new_dir,0,sizeof(FilesStruct)); 
    new_dir->x = 7; 
    new_dir->text = 'g'; 
    printf("new dir: %d,%c\n",new_dir->x,new_dir->text); 

    return 0; 
} 

回答

9
FilesStruct *old_dir; 
memset(old_dir,0,sizeof(FilesStruct)); 

试图写入一个未初始化指针。这导致未定义的行为,包括可能的崩溃。它的运气(好或坏,取决于你如何看待它),这种行为的第一个实例没有崩溃。

您需要为old_dir分配内存。要做到这一点,最简单的方法是声明它的堆栈

FilesStruct old_dir; 
memset(&old_dir,0,sizeof(old_dir)); 

上,或者你可以在堆上动态分配(确保调用free当你不再需要的对象)

FilesStruct *old_dir = calloc(1, sizeof(*old_dir); 
/* use old_dir */ 
free(old_dir); 

的同样适用于new_dir进一步向下代码。

+0

哦,我正打算使用的memset作为初始化器,你猜我是非常错误。 所以我的声明只声明一个指针,而不是底层结构;因此,我需要在memsetting之前分配内存到0? –

+0

@Noob是的,这就是 – simonc

+0

感谢您的帮助! –

3

old_dirnew_dir都没有被初始化,所以这是未定义的行为。一个解决办法是在栈上分配两个变量:

FilesStruct old_dir; 
//... 
FilesStruct new_dir; 

,并使用操作者&以获得地址调用memset时:

memset(&old_dir,0,sizeof(FilesStruct)); 
3
FilesStruct *old_dir; 

这定义了FilesStruct指针。它是未初始化的,所以它实际上并不指向FilesStruct的任何存储。

memset(old_dir,0,sizeof(FilesStruct)); 

会告诉memset的在零出任何old_dir点,但作为指针未初始化,你得到了一个未定义的行为。

您需要为指针提供存储空间,例如

FilesStruct *old_dir = malloc(sizeof(FilesStruct)); 

在你的情况,你并不真的需要一个指针或动态分配的内存,你可能会做

FilesStruct old_dir; 
memset(&old_dir,0,sizeof(FilesStruct)); 
old_dir.x = 3; 
old_dir.text = 'c'; 
printf("old dir: %d,%c\n",old_dir.x,old_dir.text);