C 结构中的指针赋值不起作用,为什么值不变?
对于一个学校项目,我应该只使用链表结构实现UNIX文件系统的简化版本。我目前的mkfs()函数有一个问题,它应该只是初始化一个文件系统 创建我正在使用的结构的头文件如下:C 结构中的指针赋值不起作用,为什么值不变?,c,pointers,struct,segmentation-fault,variable-assignment,C,Pointers,Struct,Segmentation Fault,Variable Assignment,对于一个学校项目,我应该只使用链表结构实现UNIX文件系统的简化版本。我目前的mkfs()函数有一个问题,它应该只是初始化一个文件系统 创建我正在使用的结构的头文件如下: typedef struct Lines { char line[82]; struct Lines *next; } Lines; typedef struct Node { char *name; int id; struct Node *parent; struct Node *next;
typedef struct Lines {
char line[82];
struct Lines *next;
} Lines;
typedef struct Node {
char *name;
int id;
struct Node *parent;
struct Node *next;
union {
char line[82];
struct Node *children;
} contents;
} Node;
typedef struct Filesystem {
char *name;
struct Node *root;
struct Node *current;
} Filesystem;
下面是我的单独文件中的方法,其中包含此头文件:
void mkfs(Filesystem *files) {
Node *root = NULL; /* Creates a pointer to the directory we will use as
* the root directory for this filesystem*/
files = (Filesystem *)malloc(sizeof(*files)); /* Allocates space for the the
* filesystem structure */
if(files == NULL){ /* If there is no memory available, prints error message
* and does nothing else */
printf("Memory allocation failed!\n");
} else {
root = (Node *)malloc(sizeof(*root)); /* Allocates space for the root
* directory of the filesystem. */
if(root == NULL) { /* If there is no memory available, prints error
* message and frees memory obtained thus far, but then
* does nothing else */
printf("Memory allocation failed!\n");
free(files);
} else {
/* Allocates space for the root directory's name string */
root->name= (char *)malloc(sizeof(char)*(strlen("/")+1));
if(root->name == NULL) { /* If there is no memory available, prints error
* message and frees memory obtained thus far,
* but then does nothing else */
printf("Memory allocation failed!\n");
free(files);
free(root);
} else {
root->name = "/"; /* Defines the root directory as being named by the
* forward slash */ /* DO STR CPY HERE ITS CHANGING THE ADDRESS */
root->contents.children = NULL;
root->next = NULL;
root->parent = NULL; /* UHH CHECK ON THIS NOOO CLUE IF ITS RIGHT FUUU*/
files->root = root; /* The filesystems pointer to a directory is set
* to point to the root directory we just allocated
* space for and set up */
files->current = root; /* Sets the filesystems current directory to
* point to the root directory as well, because
* it is the only directory in existence for this
* filesystem at this point. */
}
}
}
}
我遇到的问题是,当我运行gdb并单步遍历每一行时,最后两行赋值并没有改变file->root和file->current的内容。
例如,在这里我打印文件->根目录的内容,运行行文件->根目录=根目录,然后再次打印,您可以看到地址没有更改。但是,如果我只是打印root,即我试图将其分配给的对象,它显然有一个不同的值,files->root应该设置为:
(gdb) print files->root
$12 = (struct Node *) 0x400660
(gdb) step
(gdb) print files->root
$13 = (struct Node *) 0x400660
(gdb) print root
$14 = (Node *) 0x602030
有人知道为什么在这种情况下任务可能不起作用吗?这是目前破坏我的整个项目,所以任何洞察将不胜感激。谢谢你 看起来您的
mkfs
函数正在接受指向已存在的文件系统的指针,然后您试图在新的内存位置为新的文件系统分配内存。对于这样的函数,有两种常见的约定:要么不接受参数并返回指向结构的指针,要么接受指向已分配结构的指针并填充该结构。看起来数据没有改变的原因是,实际上您正在创建和填充第二个结构,并且使调用方的结构保持不变
以下是第一种情况的示例,将函数简化为内存分配部分:
Filesystem * mkfs() {
Filesystem *files = (Filesystem *)malloc(sizeof(Filesystem));
// (error handing omitted for brevity)
// populate the files struct as appropriate...
Node *root = (Node *)malloc(sizeof(Node));
files->root = root;
// etc, etc as you currently have
return files;
}
// In this case you should also provide a way for the caller to free a filesystem,
// which will free everything you allocated during mkfs:
void freefs(Filessystem *files) {
// first free any buffers you allocated inside the struct. For example:
free(files->root);
// then free the main filesystem struct
free(files);
}
然后调用方使用这两个函数处理这个对象。例如:
int main() {
Filesystem *files = mkfs();
// now "files" is ready to use
freefs(files); // free the objects when we're done with them.
}
int main() {
Filesystem *files = (Filesystem *)malloc(sizeof(Filesystem));
mkfs(files);
// now "files" is ready to use
freefs(files); // free the objects when we're done with them.
}
下面是第二种情况的示例,假设调用方已经分配了适当的缓冲区,只需填充:
void mkfs(Filesystem *files) {
// populate the files struct as appropriate...
Node *root = (Node *)malloc(sizeof(Node));
files->root = root;
// etc, etc as you currently have
}
void freefs(Filesystem *files) {
// still need to clean up all of the ancillary objects
free(files->root);
// etc, etc
}
在这种情况下,调用函数还有一些工作要做。例如:
int main() {
Filesystem *files = mkfs();
// now "files" is ready to use
freefs(files); // free the objects when we're done with them.
}
int main() {
Filesystem *files = (Filesystem *)malloc(sizeof(Filesystem));
mkfs(files);
// now "files" is ready to use
freefs(files); // free the objects when we're done with them.
}
两种模式都是有效的;如果您希望调用者能够控制内存的分配方式,那么前者非常有用。例如,调用方可能决定在堆栈而不是堆上分配文件系统:
int main() {
Filesystem files;
mkfs(&files);
// now "files" is ready to use
freefs(&files); // free the ancillary objects when we're done with them.
// "files" is still allocated here, but it's no longer valid
}
后者代表调用者处理分配。因为你的函数在堆上分配了更多的结构,所以在这两种情况下都需要包含一个清理函数。好的,函数定义是老师给我的,所以我必须遵循它。测试代码在其主要方法中实现了这一点:文件系统;mkfs(和文件系统);我无法回避这个问题,这就是考试的定义。如果老师告诉你要通过指针,那就迫使你走第二条路。(在我真正完成之前,我已经发布了答案;很抱歉造成了混淆。)最后的一个示例显示了与赋值相同的设置,调用方在堆栈上分配文件系统,并将其传递给mkfs
函数。好吧,我不允许更改main方法(这正是您编写的最后一段代码),我不允许更改函数声明。因此,您是说,如果main进行这种调用,我进入mkfs()后就不需要进行任何分配了吗?freefs
这是一种很好的风格(以避免内存泄漏)但是,如果main
传入一个指向缓冲区的指针,那么您不需要分配另一个缓冲区,您可以直接分配到该缓冲区。