Утечка памяти: возможная память при сканировании через valgrind - PullRequest
1 голос
/ 20 июня 2019

Я видел случайное поведение при сканировании моего кода через Valgrind. Я освободил все возможные блоки памяти, но я вижу, что Вальгринд сказал, что 1 блок освобожден неправильно.

Цель : создание 3-го уровня json с помощью cJSON.c, затем во втором блоке изменился формат json.

    #include<stdio.h>
    #include<stdlib.h>
    #include"cJSON.h"


    int main () {

    cJSON *root = NULL, *root1 = NULL , *arrays = NULL, *array = NULL;

           root = cJSON_CreateObject();
           root1 = cJSON_CreateObject();
           arrays = cJSON_CreateArray();

           cJSON_AddItemToObject(root,"check",root1);
    cJSON_AddItemToObject(root1, "innercheck",cJSON_CreateString("just to check"));

           cJSON_AddItemToObject(root1, "array", arrays);
           cJSON_AddItemToArray(arrays, array = cJSON_CreateObject());
   cJSON_AddItemToObject(array, "innnerarray", cJSON_CreateNumber(1));

           char *out = NULL;
           printf("===================================================\n");
           out = cJSON_Print(root);
           printf("%s\n", out);

           /* further operation now going to extract the value from json and readd new key */

           cJSON *json_param = NULL, *exe1 = NULL , *exe2 = NULL;

           json_param = cJSON_Parse(out);

           exe1 = cJSON_GetObjectItem(json_param , "check");
           cJSON_DeleteItemFromObject(exe1, "check");

           exe2  = cJSON_CreateObject();
           cJSON_AddItemToObject(exe2, "test", exe1);


           char *out2 = NULL;
           out2 = cJSON_Print(exe2);
           printf("====================================================\n");
           printf("%s\n", out2);

           if(root) {
                   cJSON_Delete(root);
                   root = NULL;
           }

           if(json_param) {
                   cJSON_Delete(json_param);
                   json_param = NULL;
           }

           if(out) {
                   free(out);
                   out = NULL;
           }

           if(out2) {
                   free(out2);
                   out2 = NULL;
           }

           return 0;
    }

Отчет о сканировании Valgrind:

    ==23708== Memcheck, a memory error detector
    ==23708== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==23708== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
    ==23708== Command: ./object
    ==23708== 
    ===================================================
    {
        "check":    {
            "innercheck":   "just to check",
            "array":    [{
                    "innnerarray":  1
                }]
        }
    }
    ====================================================
    {
        "test": {
            "innercheck":   "just to check",
            "array":    [{
                    "innnerarray":  1
                }]
        }
    }
    ==23708== 
    ==23708== HEAP SUMMARY:
    ==23708== in use at exit: 64 bytes in 1 blocks
    ==23708== 

> total heap usage: 29 allocs, 28 frees, 2,661 bytes allocated

    ==23708== 
    ==23708== 64 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==23708==    at 0x4C2FDFB: malloc (vg_replace_malloc.c:309)
    ==23708==    by 0x108F47: cJSON_New_Item (cJSON.c:214)
    ==23708==    by 0x10C9F8: cJSON_CreateObject (cJSON.c:2410)
    ==23708==    

> by 0x108BFA: main (object.c:35)

    ==23708== 
    ==23708== LEAK SUMMARY:
    ==23708==    definitely lost: 64 bytes in 1 blocks
    ==23708==    indirectly lost: 0 bytes in 0 blocks
    ==23708==      possibly lost: 0 bytes in 0 blocks
    ==23708==    still reachable: 0 bytes in 0 blocks
    ==23708==         suppressed: 0 bytes in 0 blocks
    ==23708== 
    ==23708== For lists of detected and suppressed errors, rerun with: -s
    ==23708== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Я освободил все возможные блоки памяти, но не смог понять, почему все еще я получаю, что 1 блок не является должным образом свободным.

1 Ответ

3 голосов
/ 20 июня 2019

Кажется, в вашем коде есть две проблемы.

Во-первых, вам нужно освободить объект exe2 (который вы выделили с помощью cJSON_CreateObject()) перед выходом.

cJSON_Delete(exe2);

Во-вторых ... Вам необходимо отсоединить объект check от json_param, прежде чем добавить его к объекту exe2.В противном случае вы получите двойное освобождение при вызове cJSON_Delete(exe2) - библиотека попытается освободить один и тот же объект дважды (поскольку один и тот же объект будет привязан как дочерний элемент к более чем одному объекту).

Итакзамените

    exe1 = cJSON_GetObjectItem(json_param, "check");
    cJSON_DeleteItemFromObject(exe1, "check");

на

    exe1 = cJSON_DetachItemFromObject(json_param, "check");

Обратите внимание, что я удалил строку cJSON_DeleteItemFromObject(exe1, "check"); - насколько я могу судить, это избыточно (если только вы не намеревались удалить * 1023).* элемент вместо).

...