使用 realloc 收缩后内存泄漏

问题描述

我不知道格式发生了什么变化,但我无法使用 Ctrl+K 将选定的块标记代码。对不起

我使用带有标志的 gcc 作为编译器并使用以下命令运行 valgrind:

valgrind --leak-check=full -q --error-exitcode=1

我正在尝试编写一个用于加法和减法的计算器。数字存储在一个固定大小的数组中,以 10000 数字系统编写:数组的每个元素都有一个分配的四位数内存:

#include <stdlib.h>
#include <limits.h>


#define ELEMENTS 8
#define NUM_INT 4   //Number of digits

typedef struct numb {
    int* digits;
    int how_many;  //How many cells with 4 digits
} numb;


void create(numb** tab) {
    *tab = realloc(*tab,ELEMENTS * sizeof(**tab)); 
    for (int i = 0; i < ELEMENTS; i++) {
        numb cell; 
        cell.digits = calloc(NUM_INT,sizeof (*cell.digits));
        cell.how_many = 1;
        (*tab)[i] = cell; // Put in original array.
     }
     (*tab)[ELEMENTS-2].digits[0] = -1; // Don't bother about the values
     (*tab)[ELEMENTS-1].digits[0] = 1;
}

valgrind 在两个函数显示一个问题:

  1. 两个结构的相加

     //help function
     int simple_add(int w,int m,int* p) {
         int number;
         int result = w + m + *p;
         if (result >= 10000) {
             *p = division(result);    //division by multiplication while P*i<=10000
             number = result - 10000*(*p);
         } else {
             number = result;
             *p = 0;
         }
         return number;
     }
    
     //problematic
     void add(numb* a,numb* b) {
         numb *big;
         numb *small;
         if (a->how_many != b->how_many) {
             small = min(a,b);  //simple min and max functions,not written for clarity
             big = max(a,b);
         } else {
             big = a;
             small = b;
         }
    
         int left = 0;
    
         int i = 0;
         while (i < small->how_many) {
             big->digits[i] = simple_add(big->digits[i],small->digits[i],&left);
             i++;
         }
    
         while (left != 0) {
             if (i == big->how_many) { 
                 if ((size_t)i*NUM_INT*sizeof(int) >= sizeof(big->digits)) { 
                     int size;
                     if ((size_t)i*NUM_INT*sizeof(int) + 2 >= INT_MAX) size = INT_MAX-1;
                     else size = (size_t)i*NUM_INT*sizeof(int) + 2;
                     big->digits = realloc(big->digits,size);
                 }
                 big->digits[i++] = left;
                 big->how_many++;
                 pom = 0;
             } else {
                 big->digits[i] = simple_add(big->digits[i],&left);
                 i++;
             }
         }
         *a = *big;
     }
    
  2. 将值设为 0

       void clear(numb* a) {
             a->digits = realloc(a->digits,NUM_INT*sizeof(int));
             a->digits[0] = 0;
             a->how_many = 1;
         }
    

对于小数字,它适用于 valgrind,没有错误。但是,随着测试文件中的值变大,我得到了 stackovflow/segmentation 错误

我展示了 valgrind 的三种类型的错误以减少混乱:

就在分段错误之前:

    Invalid free() / delete / delete[] / realloc()                                                                
==13932==    at 0x4837D7B: realloc (vg_replace_malloc.c:826)                                                            
    ==13932==    by 0x10A084: clear (address)                              
    ==13932==    by 0x10A298: interpreter (in address)                          
    ==13932==    by 0x10A375: game (in address)                            
    ==13932==    by 0x10A436: main (in address)
    
     Address 0x4a3ebc0 is 0 bytes inside a block of size 34 free'd                                                
    ==13932==    at 0x4837D7B: realloc (vg_replace_malloc.c:826)                                                            
    ==13932==    by 0x10A084: clear (in /address)                              
    ==13932==    by 0x10A298: interpreter (in address)                          
    ==13932==    by 0x10A375: game (in /address)                            
    ==13932==    by 0x10A436: main (in /address)                                 
    ==13932==  Block was alloc'd at                                                                                         ==13932==    at 0x4837D7B: realloc (vg_replace_malloc.c:826)                                                            ==13932==    by 0x10943A: add (in /address)                                  
    ==13932==    by 0x10A1F8: interpreter (in address)                          
    ==13932==    by 0x10A375: game (in address)
    
    Invalid write of size 4                                                                                       
    ==13932==    at 0x10A096: clear (in /address)                              
    ==13932==    by 0x10A298: interpreter (in /address)                          
    ==13932==    by 0x10A375: game (in /address)                            
    ==13932==    by 0x10A436: main (in /address)                                 
    ==13932==  Address 0x0 is not stack'd,malloc'd or (recently) free'd   

大多数情况下这是无效的写入或读取; invalid free 只出现一次。我不想用一大堆消息把帖子弄得乱七八糟,但如果你需要,我可以粘贴它。

创建的数组在程序执行后被释放。

请,我会很感激你的建议。对于小数字它有效,因此如果我们去大数字,我很难跟踪正在发生的事情。数字应该是

编辑 我已经运行了一些测试,发现 add 和 clear 中有错误,但我不知道如何修复它。

问题: 我必须变量并添加使用 add() 第一个为零,因此它只有一个单元格 [0] ::= num a 第二个超过 10000(例如:16547),因此它有两个单元格 [6547][1] ::= num b

**我发现问题的地方"

  1. 将 b 添加到 a;一 = 0; b = 16547

  2. clear a //假定为 0

  3. 打印出 b

    ==52293== 大小为 4 的无效读取
    ==52293== 在 0x10CC75:print_a_number (call5.c:355)
    ==52293== by 0x10D027:解释器(call5.c:397)
    ==52293== 来自 0x10D35F:rozgrywka (call5.c:453)
    ==52293== by 0x10D521: main (call5.c:496)
    ==52293== 地址 0x58c6804 是大小为 34 的块内的 4 个字节 free'd
    ==52293== 在 0x4837D7B:realloc (vg_replace_malloc.c:826)
    ==52293== by 0x10CD65:清除 (call5.c:367)
    ==52293== by 0x10D215:解释器(call5.c:426)
    ==52293== 来自 0x10D35F:rozgrywka (call5.c:453)
    ==52293== by 0x10D521: main (call5.c:496)
    ==52293== 块被分配在
    ==52293== 在 0x4837D7B:realloc (vg_replace_malloc.c:826)
    ==52293== by 0x10B887:添加 (call5.c:117)
    ==52293== by 0x10D115:解释器(call5.c:406)
    ==52293== by 0x10D35F:游戏(call5.c:453)
    ==52293== by 0x10D521: main (call5.c:496)

正如我们所记得的,清除重新分配大小并离开一个单元格。但是,其他单元格被释放。似乎第二个单元格丢失了 [1],但我不明白,如果我已将值分配给 add 中的指针 *a

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)