结构中的指针分配不工作,为啥值没有改变?

Posted

技术标签:

【中文标题】结构中的指针分配不工作,为啥值没有改变?【英文标题】:Assignment of a pointer within a struct NOT WORKING, why is the value not changing?结构中的指针分配不工作,为什么值没有改变? 【发布时间】:2013-03-20 20:08:02 【问题描述】:

对于一个学校项目,我应该只使用链表结构来实现 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;
  union 
    char line[82];
    struct Node *children;
   contents;
 Node;

typedef struct Filesystem 
  char  *name;
  struct Node *root;
  struct Node *current;
 Filesystem;

这是我的单独文件中的方法,其中 #includes 这个头文件:

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 的内容。 比如我这里打印files->root的内容,运行files->root=root这行,然后再打印,可以看到地址没有变。但是,如果我只是打印 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

有没有人知道为什么在这种情况下作业可能不起作用?这目前正在破坏我的整个项目,因此任何见解都将不胜感激。谢谢!!!

【问题讨论】:

【参考方案1】:

看起来您的mkfs 函数正在接受一个指向已经存在的Filesystem 的指针,然后您尝试在新的内存位置为新的Filesystem 分配内存。像这样的函数有两种常见的约定:要么不接受参数,返回指向结构的指针,要么接受指向已分配结构的指针,填充 那个结构。看起来数据没有变化的原因是您实际上是在创建和填充 second 结构,而调用者的结构保持不变。

这是第一种情况的示例,将函数简化为内存分配部分:

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.

这里是第二种情况的一个例子,它假设调用者已经分配了一个适当的缓冲区,并且只需要填充它:

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 = (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 传递一个指向缓冲区的指针,那么您不需要分配另一个,您可以直接分配到该缓冲区。

以上是关于结构中的指针分配不工作,为啥值没有改变?的主要内容,如果未能解决你的问题,请参考以下文章

C中结构中的指针-如何将给定的void指针的值分配给结构中的指针[关闭]

C语言free释放内存后为啥指针里的值不变?竟然还可以输出

为啥传递给函数的指针的值没有改变? [复制]

为啥通过指针分配给常量没有效果? [复制]

为啥 ++(*p) 会改变指针值?

当我尝试重新分配()结构指针数组时,为啥我的 C 程序会崩溃?