调用memset导致分段错误

7
这个程序会在我的UNIX机器上引起seg fault。我将原因缩小到第二次调用memset()。
为什么会出现这种行为?第一个“块”代码与第二个几乎相同,不是吗?如果第二个调用造成了segfault,那么第一个调用为什么没有?
我查看了其他有关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;
}
3个回答

11
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


哦,我本来想使用memset作为初始化器,看来我搞错了。所以我的声明只声明了一个指针,但没有声明底层结构;因此,在进行memsetting之前,我需要分配内存吗? - python_newbie
@Noob 是的,完全正确。 - simonc

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);

3

既没有初始化old_dir也没有初始化new_dir,所以这是未定义的行为。解决方案之一是在堆栈上分配两个变量:

FilesStruct old_dir;
//...
FilesStruct new_dir;

在调用 memset 时,可以使用 & 运算符来获取地址:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接