鱼C论坛

 找回密码
 立即注册
查看: 1303|回复: 6

[已解决]关于realloc再循环体内,第一次开辟成功,第二次失败的问题

[复制链接]
发表于 2023-4-25 21:11:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
void BSTreeDATAPush(BSTree* T)
{
    int chose;//用来限制循环体
    do
    {

        if(DATAsub == num)
        {
            num = num+4;
            BSTData* tmp = (BSTData*)realloc(T->DATA,sizeof(BSTData)*num);
            if(!tmp)
            {
                printf("%s\n",strerror(errno));
                exit(-1);
            }
            T->DATA = tmp;
            free(tmp);
            tmp = NULL;
        }
        printf("请插入数据:>");
        scanf("%d",&(T->DATA[DATAsub]));
        rewind(stdin);
        DATAsub++;
        printf("是否继续插入结点数据? 1.继续 0.退出 :>");
        scanf("%d",&chose);
        rewind(stdin);
        //以上是仅存放需排序的无序数组信息。
    } while (chose);
    printf("结点数据录入结束。\n");
    return ;
}
两个全局变量,num是专门用来开辟数组空间的变量;Datasub是数组的下标.
函数是我输入需要排序的数组用的,输入完数据它的值应该是和数组内存放的数据量是相同的。初始化接口里,已经开辟了4个int大小,在我输入第五个数据的时候,realloc没有提示出错。当第二次,也就是下标为8的时候,vscode提示分段错误。
也就是sub = 8; num = 12时,提示分段错误,还不是error报的……
我瞅了半天,也没见哪里有非法访问。      有没大佬解读一下?
最佳答案
2023-4-25 21:14:37
您的代码存在一个错误,这可能是导致问题的原因。在执行 `realloc` 后,您立即调用了 `free(tmp);`。这样做会释放刚刚重新分配的内存,而您实际上还需要使用它。将 `free(tmp);` 这一行删除,问题应该会得到解决。此外,由于不再需要释放 `tmp`,您也可以将 `tmp = NULL;` 这一行删除。

修改后的代码如下:
void BSTreeDATAPush(BSTree* T)
{
    int chose;//用来限制循环体
    do
    {

        if(DATAsub == num)
        {
            num = num+4;
            BSTData* tmp = (BSTData*)realloc(T->DATA,sizeof(BSTData)*num);
            if(!tmp)
            {
                printf("%s\n",strerror(errno));
                exit(-1);
            }
            T->DATA = tmp;
            // 删除以下两行
            // free(tmp);
            // tmp = NULL;
        }
        printf("请插入数据:>");
        scanf("%d",&(T->DATA[DATAsub]));
        rewind(stdin);
        DATAsub++;
        printf("是否继续插入结点数据? 1.继续 0.退出 :>");
        scanf("%d",&chose);
        rewind(stdin);
        //以上是仅存放需排序的无序数组信息。
    } while (chose);
    printf("结点数据录入结束。\n");
    return ;
}

这样修改后,您的代码应该可以正常工作。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-25 21:13:53 | 显示全部楼层
根据给出的代码,问题可能在realloc和free的使用上。重点如下:

- realloc函数返回的是一个指针,该指针指向重新分配大小后的空间。所以这里需要将 realloc 的返回值赋值给 tmp,而不是 BSTData* 类型的 T->DATA。
- 在进行 realloc 调用之后,我们无需再次释放旧内存块,因为 realloc 函数已经执行了此操作。
- 需要仔细检查调用realloc之前数据数组 DATA 中的所有访问是否都在有效范围内。这也是引起段错误的一种常见原因。

请看修改后的代码:


void BSTreeDATAPush(BSTree* T)
{
    int chose;//用来限制循环体
    do
    {
        if(DATAsub == num) {
            num = num+4;
            BSTData* tmp = (BSTData*)realloc(T->DATA,sizeof(BSTData)*num);
            if(!tmp) {
                printf("%s\n",strerror(errno));
                exit(-1);
            }
            T->DATA = tmp; // 此处将 realloc 函数返回值赋值给 T->DATA
        }

        printf("请插入数据:>");
        scanf("%d",&(T->DATA[DATAsub]));
        rewind(stdin);
        DATAsub++;
        printf("是否继续插入结点数据? 1.继续 0.退出 :>");
        scanf("%d",&chose);
        rewind(stdin);
        //以上是仅存放需排序的无序数组信息。
    } while (chose);
    printf("结点数据录入结束。\n");
    return ;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-25 21:14:37 | 显示全部楼层    本楼为最佳答案   
您的代码存在一个错误,这可能是导致问题的原因。在执行 `realloc` 后,您立即调用了 `free(tmp);`。这样做会释放刚刚重新分配的内存,而您实际上还需要使用它。将 `free(tmp);` 这一行删除,问题应该会得到解决。此外,由于不再需要释放 `tmp`,您也可以将 `tmp = NULL;` 这一行删除。

修改后的代码如下:
void BSTreeDATAPush(BSTree* T)
{
    int chose;//用来限制循环体
    do
    {

        if(DATAsub == num)
        {
            num = num+4;
            BSTData* tmp = (BSTData*)realloc(T->DATA,sizeof(BSTData)*num);
            if(!tmp)
            {
                printf("%s\n",strerror(errno));
                exit(-1);
            }
            T->DATA = tmp;
            // 删除以下两行
            // free(tmp);
            // tmp = NULL;
        }
        printf("请插入数据:>");
        scanf("%d",&(T->DATA[DATAsub]));
        rewind(stdin);
        DATAsub++;
        printf("是否继续插入结点数据? 1.继续 0.退出 :>");
        scanf("%d",&chose);
        rewind(stdin);
        //以上是仅存放需排序的无序数组信息。
    } while (chose);
    printf("结点数据录入结束。\n");
    return ;
}

这样修改后,您的代码应该可以正常工作。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-25 21:19:19 | 显示全部楼层
isdkz 发表于 2023-4-25 21:14
您的代码存在一个错误,这可能是导致问题的原因。在执行 `realloc` 后,您立即调用了 `free(tmp);`。这样做 ...

谢谢,代码可以跑了,但是不释放会造成内存泄漏吧?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-25 21:21:00 | 显示全部楼层
Filthy-ice 发表于 2023-4-25 21:19
谢谢,代码可以跑了,但是不释放会造成内存泄漏吧?

不需要担心内存泄漏。在您的示例代码中,realloc用于重新分配内存。当realloc成功时,它会自动处理原始内存块的释放。所以,在这种情况下,您不需要手动释放原始内存块。

当realloc返回新的内存地址时,它已经在内部处理了原始内存块的释放,所以您只需关心新返回的内存地址。在这种情况下,手动释放tmp实际上是错误的,因为它会释放已经重新分配给T->DATA的内存。

一般来说,您需要在程序结束时或不再需要这些内存时手动释放内存。在这个例子中,当您不再需要T->DATA时,您应该调用`free(T->DATA);`来释放内存。这通常发生在程序结束前的某个地方,或者在您不再需要BSTree结构时。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-25 21:23:39 | 显示全部楼层
sfqxx 发表于 2023-4-25 21:13
根据给出的代码,问题可能在realloc和free的使用上。重点如下:

- realloc函数返回的是一个指针,该指针 ...

明白了,学蒙了,是开辟的数组不再使用时需要释放。谢谢答疑。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-25 21:23:58 | 显示全部楼层
Filthy-ice 发表于 2023-4-25 21:23
明白了,学蒙了,是开辟的数组不再使用时需要释放。谢谢答疑。

最佳绝缘体
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-24 21:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表