两个看似相同的代码片段具有不同的结果(将指针传递给结构)

时间:2013-03-29 08:55:18

标签: c pointers struct typedef

我刚才创建了以下代码来帮助调试我们必须编写的C项目,它最终应该模拟UNIX文件系统。我一直在努力弄清楚为什么两个看似相同的代码块会产生不同的输出。当我通过在main()文件中键入相同的代码行来模拟我的函数mkfs()应该具有的相同行为时,它工作得很好,但是当我尝试使用该函数时(字面上相同的代码行! !!!!!),它只是说RUN FAILED。当我在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);
}

2 个答案:

答案 0 :(得分:2)

当你打这样的电话时

mkfs(f);

f的副本传递给mkfs。 该副本是被更改的副本(即malloc的返回值用于初始化该副本。但是,f中的main不会更改。

因此当你做

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

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

您的计划中还存在其他问题

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

答案 1 :(得分: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);
    ...
}