a905448839 发表于 2023-6-26 22:10:22

发了两次贴还是没搞懂为什么释放内存会错。。。拜托求解!

首先申明此代码不释放内存已经验证通过测试题检测

题目:

设计函数分别求两个一元多项式的乘积与和。
输入格式:

输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:

输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。
输入样例:

4 3 4 -5 26 1-2 0
3 5 20-7 43 1

输出样例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

我的代码:
#include <stdio.h>
#include <stdlib.h>

typedef struct Node *node;
struct Node
{
    int x;
    int z;
    node next;
};

node read();
void print(node list);
node he(node list1,node list2);
node ji(node list1,node list2);
void freeList(node head);

node read()
{
      int i;
      scanf("%d",&i);
      node head = (node)malloc(sizeof(node));
      head->next = NULL;
      node p = head;
      
      while(i--)
      {
                node temp = (node)malloc(sizeof(node));
                scanf("%d %d",&temp->x,&temp->z);
                p->next = temp;
                p = p->next;
      }
      p->next = NULL;
      
      return head;
}

node he(node list1,node list2)
{
      node temp;
      node head = (node)malloc(sizeof(struct Node));
      head->next = NULL;
      node p = head;
      
      if(list2->next == NULL)
      {
      
                return list1;

                }
      else
      {
                list1 = list1->next;
                list2 = list2->next;

                while(list1 && list2)
                {
                        
                        temp = (node)malloc(sizeof(struct Node));
                        if(list1->z == list2->z)
                        {      
                              temp->x = list1->x + list2->x;
                              temp->z = list1->z;
                              list1 = list1->next;
                              list2 = list2->next;
                        }
                        else if(list1->z > list2->z)
                        {
                              temp->x = list1->x;
                              temp->z = list1->z;
                              list1 = list1->next;
                        }
                        else
                        {
                              temp->x = list2->x;
                              temp->z = list2->z;
                              list2 = list2->next;
                        }
                        p->next = temp;
                        p = p->next;                        
                }
                for(;list1;list1 = list1->next)temp = (node)malloc(sizeof(struct Node)),temp->x = list1->x,temp->z = list1->z,p->next = temp,p = p->next;
                for(;list2;list2 = list2->next)temp = (node)malloc(sizeof(struct Node)),temp->x = list2->x,temp->z = list2->z,p->next = temp,p = p->next;
                p->next = NULL;
               
            
      return head;
      }
}

node ji(node list1,node list2)
{
      
      node t,L = (node)malloc(sizeof(struct Node));
      L->next = NULL;
      list1 = list1->next;
      list2 = list2->next;
               
      for(list1;list1;list1=list1->next)
      {
                node temp;
                node head = (node)malloc(sizeof(struct Node));
                head->next = NULL;
                node p = head;
                for(t = list2;t;t=t->next)
                {
                        temp = (node)malloc(sizeof(struct Node));
                        temp->x = list1->x * t->x;
                        temp->z = list1->z + t->z;

                        p->next = temp;
                        p = p->next;
                }
                p->next = NULL;
            
                printf("合并前head:");
                print(head);
                printf("合并前L:");
                print(L);
                L = he(head,L);
                printf("合并后head:");
                print(head);
                printf("合并后L:");
                print(L);


                freeList(head);



      }
      //L->next = NULL;
      return L;
               
}

void freeList(node head)
{
    node temp;
    while (head != NULL)
      {
      temp = head;
      head = head->next;
      free(temp);
    }
}

void print(node list)
{
//        node t = list;
        int flag = 1;
        if(list->next)
        list = list->next;
        else
        {
                printf("0 0\n");
                return;
       }
        for(;list;list = list->next)
        {
                if(!flag && list->x)   //控制空格输出
                        printf(" ");
                if(list->x){   // 如果系数为 0,不输出
                        printf("%d %d",list->x,list->z);
                        flag =0;               
                }
        }
        if(flag)
                printf("0 0");
        printf("\n");
}



int main()
{
    node list1,list2;
    list1 = read();
    list2 = read();

//   print(list1);
//   print(list2);
      print(ji(list1,list2));
       // print(he(list1,list2));
      
      freeList(list1);
      freeList(list2);

return 0;
}

问题我在求两个一元多项式乘积的函数node ji(node list1,node list2);
里释放掉一个临时生成的单链表(因为一元多项式乘积是依次各项相乘再相加 从而我遍历了两个一元多项式相乘另一个多项式 前一个每一项的多项式乘以后一个多项式每一项生成一个分配了空间的临时链表头节点为head然后传入求和函数node he(node list1,node list2);
合并掉相同的指数项 得到一个新的合并后并分配了内存空间的链表头节点为L 这个新链表是在求和函数node he(node list1,node list2);中新生成的链表我理解应该来说是和求积函数node ji(node list1,node list2);
的head链表是相互独立的存在所以free掉这个临时的单链表然后进入到第一个一元多项式下一个项依次乘以另一个多项式的项生成新的链表头节点为head但是我free掉head这个链表之后L链表就受到影响 L链表是求和里面return出来的 请问大佬是什么原因了! 拜托求解!)

这是在求积函数中测试段代码和释放内存函数
printf("合并前head:");
                print(head);
                printf("合并前L:");
                print(L);
                L = he(head,L);
                printf("合并后head:");
                print(head);
                printf("合并后L:");
                print(L);


                freeList(head);



sfqxx 发表于 2023-6-26 22:12:45

问题出在这段代码中:

printf("合并前head:");
print(head);
printf("合并前L:");
print(L);
L = he(head,L);
printf("合并后head:");
print(head);
printf("合并后L:");
print(L);

freeList(head);
在执行L = he(head, L);之后,L的值被修改为了合并后的链表,而head仍然指向原来的链表。所以当执行freeList(head);时,实际上是释放了合并前的临时链表,但是L仍然指向这个已经被释放的内存空间。

解决这个问题的方法是,在释放完合并前的链表之后,将head赋值为NULL,避免对已经释放的内存进行操作。修改的代码如下:

printf("合并前head:");
print(head);
printf("合并前L:");
print(L);
L = he(head, L);
printf("合并后head:");
print(head);
printf("合并后L:");
print(L);

freeList(head);
head = NULL;
这样就可以确保在释放内存之后不再使用已经释放的指针了。

isdkz 发表于 2023-6-26 22:17:32

您的问题在于,您试图释放在he()函数内部创建并返回的链表(通过L = he(head,L);语句),然后立即释放该链表的原始版本( head )。在he()函数中,您并没有创建新的节点,而是重新使用了head和L中的节点。这就意味着L和head实际上是共享一些节点的,这就解释了为什么当你释放head时, L也受到影响。

所以,当您在ji()函数中执行freeList(head);时,其实就是释放了L中的一部分或全部节点。这样做是不正确的,因为这些节点仍在L中使用。在释放head后, L中的这些节点已经被释放,所以再次访问它们(例如,通过print(L) )就会出现错误。

解决这个问题的一种方法是,在he()函数中创建新的节点,而不是重用head和L中的节点。这样,您可以安全地在ji()函数中释放head ,因为它不再与L共享任何节点。

以下是一种可能的解决方案,将您的he()函数修改为:

node he(node list1,node list2)
{
    node head = (node)malloc(sizeof(struct Node));
    head->next = NULL;
    node p = head;

    list1 = list1->next;
    list2 = list2->next;

    while(list1 && list2)
    {
      node temp = (node)malloc(sizeof(struct Node));
      if(list1->z == list2->z)
      {      
            temp->x = list1->x + list2->x;
            temp->z = list1->z;
            list1 = list1->next;
            list2 = list2->next;
      }
      else if(list1->z > list2->z)
      {
            temp->x = list1->x;
            temp->z = list1->z;
            list1 = list1->next;
      }
      else
      {
            temp->x = list2->x;
            temp->z = list2->z;
            list2 = list2->next;
      }
      p->next = temp;
      p = p->next;                        
    }

    while(list1) {
      node temp = (node)malloc(sizeof(struct Node));
      temp->x = list1->x;
      temp->z = list1->z;
      p->next = temp;
      p = p->next;
      list1 = list1->next;
    }

    while(list2) {
      node temp = (node)malloc(sizeof(struct Node));
      temp->x = list2->x;
      temp->z = list2->z;
      p->next = temp;
      p = p->next;
      list2 = list2->next;
    }

    p->next = NULL;

    return head;
}

我这里对您原有的代码进行了一些修改,使其在合并链表时,始终生成新的节点,而不是复用原有的节点。这样就解决了原有的问题。希望这个解答对您有所帮助!

a905448839 发表于 2023-6-26 23:18:51

isdkz 发表于 2023-6-26 22:17
您的问题在于,您试图释放在he()函数内部创建并返回的链表(通过L = he(head,L);语句),然后立即 ...

感谢!

歌者文明清理员 发表于 2023-6-27 08:13:19

sfqxx 发表于 2023-6-26 22:12
问题出在这段代码中:




555你能不能罢工一天

sfqxx 发表于 2023-6-27 09:12:03

歌者文明清理员 发表于 2023-6-27 08:13
555你能不能罢工一天

不可以{:10_337:}

歌者文明清理员 发表于 2023-6-27 09:15:11

sfqxx 发表于 2023-6-27 09:12
不可以

哎(叹息)

a905448839 发表于 2023-6-27 11:59:24

还有个问题能回答我一下吗?为什么你给出的代码 temp结构体指针要在每次循环里定义分配内存空间。 而我是在he函数一开始就声明一个temp结构体指针,再在每个循环里定义malloc分配内存空间。这两种做法有什么区别吗?
页: [1]
查看完整版本: 发了两次贴还是没搞懂为什么释放内存会错。。。拜托求解!