I have written some code that stores values inside a array of arrays. I am releasing the memory in my release method but Valgrind still reports the following:

==640== 
==640== HEAP SUMMARY:
==640==     in use at exit: 6,094 bytes in 33 blocks
==640==   total heap usage: 12,040 allocs, 12,007 frees, 24,146,162 bytes allocated
==640== 
==640== LEAK SUMMARY:
==640==    definitely lost: 0 bytes in 0 blocks
==640==    indirectly lost: 0 bytes in 0 blocks
==640==      possibly lost: 0 bytes in 0 blocks
==640==    still reachable: 6,094 bytes in 33 blocks
==640==         suppressed: 0 bytes in 0 blocks
==640== Rerun with --leak-check=full to see details of leaked memory
==640== 
==640== For counts of detected and suppressed errors, rerun with: -v
==640== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

My code is as follows. I first allocate a heap and insert keys in 1 array. Then I have a 2D array (array within arrays) to hold the keys. After inserting, I would like to release the memory.

I cant find where this memory is still active. Can someone please help? Thanks!

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>



/*

Note that this hashmap is required to be a multimap: that is, same
key can be associated to multiple values simultaneously. However,
the same key can be associated to the same value at most once. That is,
if you insert the key-value pairs (1,2), (1,5) and (1,2) to the map,
the key 1 has two associated values, 2 and 5.

*/

struct hashmap
{
    int** value;
    int* key;


    int keylength;
    int x;
    int y;
};

typedef struct hashmap hashmap;

/*

hashmap* hm_initialize();

Dynamically allocates a new hashmap and returns a pointer to it.

*/

hashmap* hm_initialize()
{

    hashmap *hm = malloc(sizeof(hashmap));

    hm->value = (int**)malloc(sizeof(int*));



    hm->value[0] = (int*)malloc(sizeof(int));
    hm->value[0][0] = -999999991;

    hm->key = (int*)malloc(sizeof(int));
    hm->key[0] = -999999991;

    hm->keylength = 1;
    hm->x = 1;
    hm->y = 1;

    return hm;
};

/*

void hm_release(struct hashmap*);

Releases all memory allocated for the given hashmap.

*/

void hm_release(struct hashmap* hm)
{



    free(hm->key);

    for(int x = 0; x<hm->x;x++)
    {
        free(hm->value[x]);
    }

    free(hm->value);
    free(hm);
}

/*

void hm_insert(struct hashmap* hm, int key, int value);

Inserts the key-value pair to the hashmap.

*/

void hm_insert(struct hashmap* hm, int key, int value)
{

   // printf("KEY: %d , Value: %d \n", key, value);

    int flagkey = 0;
    int flagvalue = 0;
    int flaglocationkey;
    int flaglocationvalue;
    int valueexists = 0;
    int counter1 = 0;



    for(int x = 0;x<hm->keylength;x++)
    {

        //printf("LOOP: %d \n");

        if(hm->key[x] == key)
        {

             //Old Key Exists and is Active
            flagkey = 1;
            flaglocationvalue = x;


        }



    }

     //printf("CONTENTS: ");
    //int counter1 = 0;
    //while(hm->key[counter1] != -99999)
    //{
      //    printf(" %d ", hm->key[counter1]);
     //   counter1++;
    //}




    if(flagkey == 0)
    {

        hm->key = realloc(hm->key,(hm->keylength+1)*sizeof(int));
        hm->key[hm->keylength-1] = key;
        hm->key[hm->keylength] = -999999991;

        hm->keylength = hm->keylength + 1;



        ////////////

        hm->value = (int**)realloc(hm->value,(hm->x+1)*sizeof(int*));
        hm->value[hm->x] = (int*)malloc(sizeof(int));
        hm->value[hm->x][0] = -999999991;
        hm->value[hm->x-1] = (int*)realloc(hm->value[hm->x-1],2*sizeof(int));
        hm->value[hm->x-1][1] = -999999991;
        hm->value[hm->x-1][0] = value;




        hm->x++;


    }

    if(flagkey == 1)
    {
          printf("FOUND KEY \n");

       printf("CONTENTS OF VAL1: %d \n", hm->value[flaglocationvalue][0]);

        while((hm->value[flaglocationvalue][counter1]) != -999999991)
        {


            if(hm->value[flaglocationvalue][counter1] == value)
            {
                 printf("TRUE");
                valueexists = 1;
            }

            counter1++;

        }

        printf("CONTENTS OF VAL2: %d \n", hm->value[flaglocationvalue][counter1]);
        printf("LENGTH %d \n", counter1);

        if(valueexists == 0)
        {
            hm->value[flaglocationvalue] = (int*)realloc((hm->value[flaglocationvalue]),(counter1+2)*sizeof(int));
            hm->value[flaglocationvalue][counter1] = value;
             hm->value[flaglocationvalue][counter1+1] = -999999991;
        }



    }






}

/*

Returns the count of how many values the given key is currently
associated with.

int hm_count(struct hashmap* hm, int key);

*/

int hm_count(struct hashmap* hm, int key)
{
    int counter1 = 0;
    int flaglocationvalue;


    for(int x = 0;x<hm->keylength;x++)
    {

    if(hm->key[x] == key)
    {

        //Old Key Exists and is Active
        flaglocationvalue = x;
        printf("Location: %d  \n", flaglocationvalue);
        printf("Location: %d  \n", hm->value[flaglocationvalue][1]);

        break;


    }
    }

     while((hm->value[flaglocationvalue][counter1]) != -999999991)
     {
         counter1++;
         printf("ELEMENTS: %d ", counter1);
     }

    return counter1;
}

/*

Removes the association of key and value from the hashmap. If there
is no such association present, does nothing.

*/

void hm_remove(struct hashmap* hm, int key, int value)
{



}

/*

void hm_get(struct hashmap* hm, int key, int* arr);

Collects all values that are currently associated with the given
key into the array arr. You can assume that arr contains enough
room for all these keys when this function is called.

*/

void hm_get(struct hashmap* hm, int key, int* arr)
{

    int counter1 = 0;
    int flaglocationvalue;


    for(int x = 0;x<hm->keylength;x++)
    {

        if(hm->key[x] == key)
        {

            //Old Key Exists and is Active
            flaglocationvalue = x;


            break;


        }
        }

        while((hm->value[flaglocationvalue][counter1]) != -999999991)
        {
            arr[counter1] = (hm->value[flaglocationvalue][counter1]);
            counter1++;

        }




}

Check the rest of your program to see if those functions are actually being called.

They are all being used in the program. I ran the program with nothing being called and the same thing happens.

can you post the entire program? If it is very large then zip up the file(s) and attach the zip file to your post (see the Files like above the editor)

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "hashmap.h"

#define TESTSIZE 10000

int main() {
  int i, j, c;
  int a[TESTSIZE], b[TESTSIZE];
  int* tmp;

  struct hashmap* h;
  h = hm_initialize();

  printf("Filling up map\n");
  for(i = -1000; i < 1001; i++) {
    hm_insert(h, i, i/2);
    hm_insert(h, -i, i*i*i);
    hm_insert(h, i, i*i);
    hm_insert(h, i, i*i);
  }
  assert(hm_count(h, 500) == 3);

  printf("Starting test one\n");
  for(i = 1000; i >= -1000; i--) {
    hm_remove(h, i, i+2);
    hm_remove(h, i, i/2);
    assert(i*i < 5 || hm_count(h, i) == 2);
  }

  hm_release(h);
  h = hm_initialize();

  printf("Starting test two\n");

  tmp = malloc(sizeof(int) * TESTSIZE);
  for(i = 0; i < TESTSIZE; i++) {
    a[i] = rand(); b[i] = rand();
    hm_insert(h, a[i], b[i]);
  }  
  for(i = 0; i < TESTSIZE; i++) {
    c = hm_count(h, a[i]);
    assert(c > 0);
    hm_get(h, a[i], tmp);
    j = 0;
    while(1) {
      if(tmp[j] == b[i]) break;
      assert(j++ < c);
    }
  }

  printf("Starting test three\n");

  for(i = 0; i < TESTSIZE; i++) {
    hm_remove(h, a[i], b[i]);
    c = hm_count(h, a[i]);
    if(c > 0) {
      hm_get(h, a[i], tmp);
      for(j = 0; j < c; j++) {
        assert(tmp[j] != b[i]);
      }
    }
  }

  for(i = 0; i < TESTSIZE; i++) {
    assert(hm_count(h, a[i]) == 0);
  }

  free(tmp);
  hm_release(h);

  printf("All tests finished successfully\n");

}

did you mean to make hm_remove() an empty function?

Yes. Ignore all the remove functions because I have not completed that code yet. What I meant to say before is that if you remove this "controller" code that tests my code, valgrind will STILL report the same thing. How is this possible when my code isnt even being called.

If you remove the controller code then your program doesn't have a main(), and no main() then the compiler doesn't generate the executable. So you are probably running some previous version of the program. Delete the executable then rebuild the program without the controller and see if the excutable is present. My bet is that it will not be present.

No. I deleted the contents of the main program. There is a main inside but all it does is printf("Hi");

Can you try running this code?

when I run it I get this assertion error

TRUECONTENTS OF VAL2: 1000000
LENGTH 2
Location: 1001
Location: 250
ELEMENTS: 1 ELEMENTS: 2 ELEMENTS: 3 Starting test one
Location: 1
Location: 500
ELEMENTS: 1 ELEMENTS: 2 ELEMENTS: 3 Assertion failed: i*i < 5 || hm_count(h,
== 2, file c:\dvlp\test1\test1\main.c, line 29

commented: Thanks! +0

Thats because remove hasnt been implemented, try replacing with this code:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "hashmap.h"

#define TESTSIZE 10000

int main() {
    int i, j, c;
    int a[TESTSIZE], b[TESTSIZE];
    int* tmp;

    struct hashmap* h;
    h = hm_initialize();

    printf("Filling up map\n");
    for(i = -1000; i < 1001; i++) {
        hm_insert(h, i, i/2);
        hm_insert(h, -i, i*i*i);
        hm_insert(h, i, i*i);
        hm_insert(h, i, i*i);
    }
    assert(hm_count(h, 500) == 3);



    hm_release(h);
    h = hm_initialize();

    printf("Starting test two\n");


    hm_release(h);

    printf("All tests finished successfully\n");

}

then try running it with an empty main.

It seems that it is a False Positive in valgrind and there is no issue with my program. I thank you for all your help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.