为啥我的链表内容在退出函数时会消失?

Posted

技术标签:

【中文标题】为啥我的链表内容在退出函数时会消失?【英文标题】:Why is my content of linked list disappear when it exit a function?为什么我的链表内容在退出函数时会消失? 【发布时间】:2022-01-13 01:31:41 【问题描述】:

我试图扫描文件并将数据添加到链接列表中,然后将操作打印到输出文件中。我成功将操作打印到输出文件,但是当我尝试访问它时,我的链接列表的内容是空的。

然后我检查创建和链接的每个节点的地址,发现没有问题,当它在函数内部时,链接列表工作正常,但在 main() 中没有。

输入.txt 3 1 编码标记编程 1 烹饪米妮烹饪 1 园艺一分钱植物学

此代码未完成,但包含我的问题:

#include<stdio.h>
#include<ctype.h>
#include<string.h>

struct book 
    char *title;
    char *author;
    char *subject;
;
struct library 
    struct book collection;
    int num_books;
    struct library *next;
;

void AddBook(FILE *IF, FILE *OF, struct library** thislib);//function prototype

int main(void)
    FILE *IF,*OF;
    int sel,numOp,i;
    struct library *Lib=NULL;//declare head pointer
    if(((IF=fopen("library.txt","a+"))==NULL)||((OF=fopen("output.txt","w"))==NULL))//open input and output file
        printf("File cannot be open!");
    
    else   
        fscanf(IF," %d",&numOp);    //scan the number of operation from file
        for(i=0;i<numOp;i++)       //Loop according to number of operation
            if(feof(IF))            //if file pointer reach EOF break
                break;  
            fscanf(IF," %d",&sel);  //scan the type of operation
            switch(sel)
            case 1: 
                AddBook(IF,OF,&Lib);    //add the book if sel is 1
                break;
            case 2:
                
                break;
            
            printf("%s ", Lib->collection.title);   // print the title of the book but it show nothing
        
    
    return 0;


void AddBook(FILE *IF, FILE *OF, struct library** thislib)
    char title[30],author[30],subject[20];          //declare variable to hold data
    struct library *temp=NULL;                      //create a new node
    struct library *ptr=*thislib;               //create a pointer that point to head of link list
    temp=(struct library*)malloc(sizeof(struct library));   //allocate memory for the new node
    fscanf(IF," %s %s %s" ,title,author,subject);
    temp->collection.title=title;       // put the data into link list
    temp->collection.author=author;
    temp->collection.subject=subject;
    temp->next=NULL;
    if((*thislib)==NULL)
        (*thislib)=temp;                // if there is no content in link list put temp into head
    
    else
        while (ptr->next!=NULL)
        
            ptr=ptr->next;              //put node at the end of link list
        
        ptr->next=temp;
    
    fprintf(OF,"The book %s author %s subject %s has been added to the library.\n",title,author,subject);
    printf("%s ",(*thislib)->collection.title);  //this work fine but it keep updating, weren't it suppose to have the same value

【问题讨论】:

temp-&gt;collection.title=title; 将指向局部变量的指针放入列表节点。当函数返回时,这些指针变得无效。您需要制作字符串的动态副本,例如temp-&gt;collection.title=strdup(title) 嘿,它的工作非常感谢你,strcpy() 也工作吗? 在分配内存之前不能使用strcpy()strdup()malloc()strcpy() 的组合。 【参考方案1】:

    你忘了#include &lt;stdlib.h&gt;。您的代码非常未定义,因为您剪掉了malloc() 返回的高位。

    您返回了指向堆栈数组的指针。

    temp->collection.title=title;       // put the data into link list
    temp->collection.author=author;
    temp->collection.subject=subject;

得骗那些。 strdup()是你的朋友:

    temp->collection.title=strdup(title);       // put the data into link list
    temp->collection.author=strdup(author);
    temp->collection.subject=strdup(subject);

    此行在您的测试用例中失败:fscanf(IF," %d",&amp;numOp); 输入与模式不匹配;您使用未定义的numOp 进入循环。 (我通过更正输入文件轻松解决了这个问题。您应该始终检查 scanf 的返回。)

    此 scanf 导致读取问题导致废话。

    fscanf(IF," %s %s %s" ,title,author,subject);

但您的输入中有四个以空格分隔的字段。

    您的调试输出显示链接列表中的第一项,但您每次都追加到列表末尾,因此它不会更改。

“剪掉高位”的解释:

缺少#include &lt;stddef.h&gt; 的隐式声明将是int malloc(size_t),这是错误的。这在 32 位平台上有效,但在 64 位平台上无效。 int 向上转换为 void *,这不会产生正确的值。

假设malloc() 返回了0x104C000010。返回地址看起来像这样(字节顺序在这里无关紧要,原因我现在不打算讨论)

 0                                                                                                                            63
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|0|0|1|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

但是返回被解释为32位整数(大多数64平台有sizeof(int)=4),所以会被解释为

 0                                                            31
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|0|0|1|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

当转换为 struct library * 时,会导致

 0                                                                                                                            63
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

这是0x4C000010。哎呀,指向其他地方。任何事情都可能发生,但很可能是崩溃。

【讨论】:

“你剪掉了 malloc() 返回的高位”。怎么样? @MadPhysicist:隐式类型为int malloc(...);int 在现代平台上小于void * 剪掉高位是什么意思?会造成什么影响? @Joshua。这是一个很好的选择,特别是如果 OP 的 RAM > 4GiB。您可能想在答案中为 OP 拼写出来。 @Strugle: #include &lt;stdlib.h&gt; 并在启用警告的情况下进行编译。这给出了“隐式声明”的警告。

以上是关于为啥我的链表内容在退出函数时会消失?的主要内容,如果未能解决你的问题,请参考以下文章

我找不到我的链表的错误(为啥我的头指针在移动?)

刷题10:归并两个有序的链表

使用类的链表中的分段错误。我的方法正确吗?

使用类的链表

将第一个节点添加到hashmap中的链表时,为啥必须将新节点直接分配给索引指针?

递归打印类中的链表c ++