0

我刚刚创建了以下代码来帮助调试我们必须编写的 C 项目,该项目最终应该模拟 UNIX 文件系统。我一直在努力弄清楚为什么两个看似相同的代码块会产生不同的输出。当我通过在 main() 文件中键入相同的代码行来模拟我的函数 mkfs() 应该具有的相同行为时,它可以完美地工作,但是当我尝试使用该函数时(实际上是相同的代码行! !!!!!),它只是说运行失败。当我在我的 main() 函数中执行当前已注释掉的代码时,它运行良好并且确实将“/”打印到控制台,但是当我尝试创建指向文件系统的指针时,在其上调用 mkfs(),然后打印出相同的字符串,它只是不起作用。

我一定是不明白什么。这是代码,但如果您更喜欢语法突出显示,那么这里有一个指向 pastebin 的小链接:http: //pastebin.com/9yCB1iND

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

typedef struct directory {
    const char *name;
    struct file *f;
    struct directory *dir;
} Directory;

typedef struct file {
    const char *name;
    struct file *next;
    struct file *prev;
    Directory *parent;
} File;

typedef struct filesystem {
    Directory *rt;
    Directory *cd;
} Filesystem;

/* The function mkfs() initializes the Filesystem. It takes a pointer to a 
 * filesystem as its single parameter and allocates the memory needed ( it 
 * allocates the space needed to accomodate the two Directory pointers 
 * that a filesystem has). */
    void mkfs(Filesystem *files){

    /*The first malloc creates enough space for Filesystem itself*/
    files = malloc(sizeof(Filesystem));

    /*The second malloc creates enough space for a root Directory*/
    files->rt = malloc(sizeof(Directory));

    /*We make a character array with a single slash that represents root*/
    char nv[] = "/";
    /* nv is a pointer to the first element in the array nv[]. 
     * We point 'files->rt->name' to the first character in the array nv[]. */
    files->rt->name = nv;
    /* Finally, we set files->cd to point to whatever files->rt pointed too, 
     * which is the current directory "/" */
    files->cd = files->rt;
}


int main(void) {
    /*
    Filesystem *files;
    files = malloc(sizeof(Filesystem));
    files->rt = malloc(sizeof(Directory));
    char nv[] = "/";
    files->rt->name = nv;
    files->cd = files->rt;
    printf("%s", files->cd->name);

        ---------------------------------------------------------------------------
        Why does the FOLLOWING code not work when the ABOVE code should be "the same" ?
        ---------------------------------------------------------------------------
    */

    Filesystem *f;
    mkfs(f);
    printf("%s", f->cd->name);

    return (EXIT_SUCCESS);
}
4

2 回答 2

2

当你这样打电话时

mkfs(f);

的副本f被传递给 mkfs。该副本是更改的副本(即 malloc 的返回值用于初始化该副本。但是,finmain没有更改。

因此,当你这样做

printf("%s", f->cd->name); 

在 main - 这是未定义的行为,因为您正在访问未初始化的指针。

你的程序还有其他问题

nv是该功能的本地人。它的生命只有在函数返回之前。所以这是错误的。

于 2013-03-29T08:58:46.910 回答
1

mkfs功能上:

char nv[] = "/";
files->rt->name = nv;

nv是一个具有自动存储持续时间的数组,当执行超出此函数的范围时,其生命周期结束,files->rt->name成为悬空指针,取消引用会导致未定义的行为。您需要files->rt->name动态分配。

另请注意,mkfs函数需要指向 的指针Filesystem,这只是传递给它的指针的副本。对指针本身所做的更改对调用者是不可见的,这意味着当您调用时printf("%s", f->cd->name);,您正在取消引用未初始化的指针,这也会导致未定义的行为。如果要mkfs分配内存并正确初始化指针,则应传递此指针的地址:

void mkfs(Filesystem **files) {
    *files = malloc(sizeof(Filesystem));
    (*files)->rt = malloc(sizeof(Directory));
    char nv[] = "/";
    (*files)->rt->name = malloc(strlen(nv) + 1);
    strcpy((*files)->rt->name, nv);
    (*files)->cd = (*files)->rt;
}

int main(void) {
    Filesystem *f = NULL;  // <-- it's good to keep your variables initialized
    mkfs(&f);
    ...
}

如果你不需要你的函数来改变这个指针指向的内存,而不是指针本身,它可能看起来像这样:

void mkfs(Filesystem *files) {
    files->rt = malloc(sizeof(Directory));
    char nv[] = "/";
    files->rt->name = malloc(strlen(nv) + 1);
    strcpy(files->rt->name, nv);
    (*files)->cd = files->rt;
}

int main(void) {
    Filesystem *f;
    f = malloc(sizeof(Filesystem));
    mkfs(f);
    ...
}
于 2013-03-29T09:00:15.273 回答