首页 > 解决方案 > 使用 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], 0, &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   

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

创建的数组在程序结束后被释放。

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

编辑 我已经运行了一些测试,并在添加和清除中发现了错误,但我不知道如何修复它。

问题:我必须变量并添加 using add() 第一个为零,因此它只有一个单元格 [0] ::= num 第二个超过 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== 通过 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: clear (call5.c:367)
    ==52293== by 0x10D215: 解释器 (call5.c:426)
    ==52293== by 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== 由 0x10D521: 主要 (call5.c:496)

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

标签: cmemory-managementsegmentation-faultstack-overflowvalgrind

解决方案


推荐阅读