Valgrind:大小为4的无效读取,1个块中的8字节在C中的丢失记录中肯定丢失

Valgrind:大小为4的无效读取,1个块中的8字节在C中的丢失记录中肯定丢失,c,memory,memory-management,valgrind,generic-programming,C,Memory,Memory Management,Valgrind,Generic Programming,我正在尝试使用以下代码在C中创建通用映射: #include <stdlib.h> #include <stdio.h> #include "map.h" //Declaring our function, More detailed explanation at the bottom of the document static MapResult mapPutAll(Map srcMap, Map destMap); static MapResult freePa

我正在尝试使用以下代码在C中创建通用映射:

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

//Declaring our function, More detailed explanation at the bottom of the document

static MapResult mapPutAll(Map srcMap, Map destMap);
static MapResult freePair(Map map, int i);
static MapResult replacePair(Map map, int i, MapDataElement dataElement, MapKeyElement keyElement);
static int mapFind(Map map, MapKeyElement element);

struct Map_t{
    MapDataElement *values;
    MapKeyElement *keys;
    int iterator;
    int size;
    copyMapDataElements copy_value;
    copyMapKeyElements copy_key;
    freeMapDataElements free_value;
    freeMapKeyElements free_key;
    compareMapKeyElements compare;
};

Map mapCreate(copyMapDataElements copyDataElement,
              copyMapKeyElements copyKeyElement,
              freeMapDataElements freeDataElement,
              freeMapKeyElements freeKeyElement,
              compareMapKeyElements compareKeyElements) {

    if (copyDataElement == NULL || copyKeyElement == NULL ||
        freeDataElement == NULL || freeKeyElement == NULL || compareKeyElements == NULL) {
        return NULL;
    }

    Map map = malloc(sizeof(*map));
    if (map==NULL) {
        return NULL;
    }

    map->values = malloc(sizeof(MapDataElement));
    if (map->values==NULL){
        return NULL;
    }
    map->keys = malloc(sizeof(MapKeyElement));
    if (map->keys==NULL){
        return NULL;
    }
    map->iterator = 0;
    map->size = 0;
    map->copy_value = copyDataElement;
    map->copy_key = copyKeyElement;
    map->free_value = freeDataElement;
    map->free_key = freeKeyElement;
    map->compare = compareKeyElements;

    return(map);
}


void mapDestroy(Map map) {
    if (map == NULL) {
        return;
    }
    if (mapGetSize(map)==0){
        free(map->values);
        free(map->keys);
    }
    mapClear(map);
    free(map);
}

Map mapCopy(Map map) {

    if (map == NULL) {
        return NULL;
    }
    Map map_copy = mapCreate(map->copy_value, map->copy_key, map->free_value, map->free_key, map->compare);
    if (map_copy == NULL) {
        return NULL;
    }
    map_copy->iterator = map->iterator;
    map_copy->size = map->size;
    MapResult result = mapPutAll(map, map_copy);
    if (result != MAP_SUCCESS) {
        return NULL;
    }
    return map_copy;
}

int mapGetSize(Map map){
    return (map==NULL)? -1 : map->size;
}

bool mapContains(Map map, MapKeyElement element) {
    return (mapFind(map,element)<0) ? false : true;
}

MapResult mapPut(Map map, MapKeyElement keyElement, MapDataElement dataElement){
    if (map==NULL || keyElement==NULL || dataElement==NULL) {
        return MAP_NULL_ARGUMENT;
    }
    if (mapGetSize(map) == 0){
        map->values[0] = dataElement;
        map->keys = keyElement;
        map->size++;
        return MAP_SUCCESS;
    }
    if (mapContains(map, keyElement)) { //If key exists, replace corresponding value.
        int index = mapFind(map,keyElement);
        map->values[index] = dataElement;
        return MAP_SUCCESS;
    }
    for (int i=0; i<mapGetSize(map); i++){
        if (map->compare(keyElement, map->keys[i])<0) {
            int new_last_index = mapGetSize(map);
            MapDataElement ptr_temporary_values;
            MapKeyElement ptr_temporary_keys;


            ptr_temporary_values = realloc(map->values, sizeof(*map->values)*(new_last_index+1));
            map->values = ptr_temporary_values;

            ptr_temporary_keys = realloc(map->keys, sizeof(*map->keys)*(new_last_index+1));
            map->keys = ptr_temporary_keys;


            if (map->values==NULL || map->keys==NULL) return MAP_OUT_OF_MEMORY;


            for (int j=new_last_index; j>i; j--){
                map->values[j] = map->values[j-1];
                map->keys[j] = map->keys[j-1];
            }
            replacePair(map, i, dataElement, keyElement);


            if (map->values[i]==NULL || map->keys[i]==NULL) return MAP_OUT_OF_MEMORY;


            map->size++;
            return MAP_SUCCESS;
        }
    }
    int new_last_index = mapGetSize(map);
    MapDataElement ptr_temporary_values;
    MapKeyElement ptr_temporary_keys;


    ptr_temporary_values = realloc(map->values, sizeof(*map->values)*(new_last_index+1));
    map->values = ptr_temporary_values;

    ptr_temporary_keys = realloc(map->keys, sizeof(*map->keys)*(new_last_index+1));
    map->keys = ptr_temporary_keys;


    if (map->values==NULL || map->keys==NULL) return MAP_OUT_OF_MEMORY;


    map->values[new_last_index] = map->copy_value(dataElement);
    map->keys[new_last_index] = map->copy_key(keyElement);


    if (map->values[new_last_index]==NULL || map->keys[new_last_index]==NULL){
        return MAP_OUT_OF_MEMORY;
    }


    map->size++;
    return MAP_SUCCESS;
}

MapDataElement mapGet(Map map, MapKeyElement keyElement) {
    if (map == NULL || keyElement == NULL) {
        return NULL;
    }

    if (mapContains(map, keyElement) == false) {
        return NULL;
    }

    for (int i = 0; i < map->size; i++) {
        if(map->compare(map->keys[i], keyElement)  == 0) {
            return map->values[i];
        }
    }

    return NULL; //Should not get here.
}

MapResult mapRemove(Map map, MapKeyElement keyElement){
    if(map==NULL || keyElement==NULL){
        return MAP_NULL_ARGUMENT;
    }
    int size = mapGetSize(map);
    for (int i=0; i<size; i++){
        if (map->compare(map->keys[i], keyElement)==0){
            for (int j=i; j<size-1; j++){
                map->values[j] = map->values[j+1];
                map->keys[j] = map->keys[j+1];
            }
            freePair(map, size+1);
            map->size--;
            return MAP_SUCCESS;
        }
    }
    return MAP_ITEM_DOES_NOT_EXIST;
}

MapKeyElement mapGetFirst(Map map){
    if (map==NULL){
        return NULL;
    }
    map->iterator=0;
    return (mapGetSize(map)==0)? NULL : map->keys[map->iterator];
}

MapKeyElement mapGetNext(Map map){
    if (map==NULL || map->iterator==mapGetSize(map)-1){
        return NULL;
    }
    map->iterator++;
    return map->keys[map->iterator];
}

MapResult mapClear(Map map) {
    if (map == NULL) {
        return MAP_NULL_ARGUMENT;
    }
    int index = map->size-1;
    while(map->size!=0) {
        mapRemove(map, map->keys[index]);
        index = map->size-1;
    }
    return MAP_SUCCESS;
}

/**
 * mapPutAll - copies all key-value pairs from one map to another map.
 * Iterator's value is undefined after this operation.
 * @param srcMap - Map that will be copied from.
 * @param destMap - Map that will be copied to.
 * @return
 *  MAP_NULL_ARGUMENT - if a NULL was sent as map
 *  MAP_OUT_OF_MEMORY - if an allocation failed (Meaning the function for copying
 *  an element failed)
 *  MAP_SUCCESS - all the pairs of elements had been inserted successfully
 */
static MapResult mapPutAll(Map srcMap, Map destMap) {
    if (srcMap==NULL || destMap==NULL){
        return MAP_NULL_ARGUMENT;
    }
    MapResult result=MAP_SUCCESS;
    for(int i = 0; i < srcMap->size; i++) {
        result = mapPut(destMap, srcMap->keys[i], mapGet(srcMap, srcMap->keys[i]));/**problem here in first iteration*/
        if(result != MAP_SUCCESS) {
            return result;
        }
    }
    return result;
}

/**
 * freePair - frees the i th pair in the map.
 * @param map - The map to free the pair from.
 * @param i - The index of the pair to be freed.
 * @return
 *  MAP_NULL_ARGUMENT - if a NULL was sent as map.
 *  MAP_SUCCESS - all the pairs of elements had been inserted successfully
 *  or i is out of range.
 */
static MapResult freePair(Map map, int i){
    if (map==NULL){
        return MAP_NULL_ARGUMENT;
    }
    if (i<0 || i>mapGetSize(map)){
        return MAP_SUCCESS;
    }
    map->free_value(map->values[i]);
    map->free_key(map->keys[i]);
    return MAP_SUCCESS;
}

/**
 * replacePair - replace the i th pair in map with a new pair and frees the old pair.
 * @param map - The map to replace the pair from.
 * @param i - The index of the pair to be freed.
 * @param dataElement - The data element to replace the old value with.
 * @param keyElement - The key element to replace the old value with.
 * @return
 *  MAP_NULL_ARGUMENT - if a NULL was sent as map.
 *  MAP_OUT_OF_MEMORY - if an allocation failed.
 *  MAP_SUCCESS - all the pairs of elements had been inserted successfully
 *  or i is out of range.
 */
static MapResult replacePair(Map map, int i, MapDataElement dataElement, MapKeyElement keyElement){
    if (map==NULL || dataElement==NULL || keyElement==NULL){
        return MAP_NULL_ARGUMENT;
    }
    map->values[i] = dataElement;
    map->keys[i] = keyElement;
    return MAP_SUCCESS;
}

/**
* mapFind: Checks if a key element exists in the map, and returns its index in the array.
* The key element will be considered in the map if one of the key elements in the map it determined equal
* using the comparison function used to initialize the map.
*
* @param map - The map to search in.
* @param element - The element to look for. Will be compared using the
*       comparison function.
* @return
*   -1 - if one or more of the inputs is null, or if the key element was not found.
*   index of the element in the array of the map - if the key element was found in the map.
*/
static int mapFind(Map map, MapKeyElement element) {
    if(map == NULL || element == NULL) {
        return -1;
    }
    for (int i=0; i<mapGetSize(map); i++) {
        if (map->compare(element, map->keys[i]) == 0) {
            return i;
        }
    }
    return -1;
}
但我不明白为什么会发生这种情况,以及如何解决它


有人能帮我吗?

这里的代码太多了,无法理解。您一定没有正确复制密钥。这里的代码太多,无法遵循。不能正确复制密钥。
#include "test1.h"
#include <stdlib.h>
#include <stdio.h>
#include "map.h"

/** Function to be used for copying an int as a key to the map */
static MapKeyElement copyKeyInt(MapKeyElement n) {
    if (!n) {
        return NULL;
    }
    int *copy = malloc(sizeof(*copy));
    if (!copy) {
        return NULL;
    }
    *copy = *(int *) n;
    return copy;
}

/** Function to be used for copying a char as a data to the map */
static MapDataElement copyDataChar(MapDataElement n) {
    if (!n) {
        return NULL;
    }
    char *copy = malloc(sizeof(*copy));
    if (!copy) {
        return NULL;
    }
    *copy = *(char *) n;
    return (MapDataElement) copy;
}

/** Function to be used by the map for freeing elements */
static void freeInt(MapKeyElement n) {
    free(n);
}

/** Function to be used by the map for freeing elements */
static void freeChar(MapDataElement n) {
    free(n);
}

/** Function to be used by the map for comparing elements */
static int compareInts(MapKeyElement n1, MapKeyElement n2) {
    return (*(int *) n1 - *(int *) n2);
}

bool testMapCreateDestroy() {
    Map map = mapCreate(copyDataChar, copyKeyInt, freeChar, freeInt,
                        compareInts);
    ASSERT_TEST(map != NULL);
    ASSERT_TEST(mapGetSize(map) == 0);
    ASSERT_TEST(mapGetFirst(map) == NULL);
    mapDestroy(map);
    return true;

}

bool testMapAddAndSize() {
    Map map = mapCreate(copyDataChar, copyKeyInt, freeChar, freeInt,
                        compareInts);
    for (int i = 1; i < 1000; ++i) {
        char j = (char) i;
        ++j;
        ASSERT_TEST(mapPut(map, &i, &j) == MAP_SUCCESS);
        ASSERT_TEST(mapGetSize(map) == i);
    }
    printf("\n%d\n",__LINE__);
    mapDestroy(map);
    return true;
}

bool testMapGet() {
    Map map = mapCreate(copyDataChar, copyKeyInt, freeChar, freeInt,
                        compareInts);
    for (int i = 1; i < 1000; ++i) {
        char j = (char) i;
        ++j;
        ASSERT_TEST(mapPut(map, &i, &j) == MAP_SUCCESS);
        ASSERT_TEST(mapGetSize(map) == i);
    }

    for (int i = 1; i < 1000; ++i) {
        char j = (char) i;
        ++j;
        char *getVal = (char *) mapGet(map, &i);
        ASSERT_TEST(*getVal == j);
    }
    int i = 0;
    ASSERT_TEST(mapGet(map, &i) == NULL);
    i = 1000;
    ASSERT_TEST(mapGet(map, &i) == NULL);
    mapDestroy(map);
    return true;
}

bool testIterator() {
    Map map = mapCreate(copyDataChar, copyKeyInt, freeChar, freeInt,
                        compareInts);
    for (int i = 1; i < 400; ++i) {
        char j = (char) i;
        ++j;
        ASSERT_TEST(mapPut(map, &i, &j) == MAP_SUCCESS);
    }
    for (int i = 800; i >= 400; --i) {
        char j = (char) i;
        ++j;
        ASSERT_TEST(mapPut(map, &i, &j) == MAP_SUCCESS);
    }

    for (int i = 801; i < 1000; ++i) {
        char j = (char) i;
        ++j;
        ASSERT_TEST(mapPut(map, &i, &j) == MAP_SUCCESS);
    }

    int i = 1;
    MAP_FOREACH(int *, iter, map) {
        ASSERT_TEST(*iter == i);
        i++;
    }

    mapDestroy(map);
    return true;
}

void runTest1() {
    RUN_TEST(testMapCreateDestroy);
    RUN_TEST(testMapAddAndSize);
    RUN_TEST(testMapGet);
    RUN_TEST(testIterator);
}
#ifndef TEST1_H_
#define TEST1_H_

#include <stdbool.h>
#include <stdio.h>

void runTest1();

/**
 * These macros are here to help you create tests more easily and keep them
 * clear
 *
 * The basic idea with unit-testing is create a test function for every real
 * function and inside the test function declare some variables and execute the
 * function under test.
 *
 * Use the ASSERT_TEST to verify correctness of values.
 */

/**
 * Evaluates b and continues if b is true.
 * If b is false, ends the test by returning false and prints a detailed
 * message about the failure.
 */
#define ASSERT_TEST(b) do { \
        if (!(b)) { \
                printf("\nAssertion failed at %s:%d %s ",__FILE__,__LINE__,#b); \
                return false; \
        } \
} while (0)

/**
 * Macro used for running a test from the main function
 */
#define RUN_TEST(test) do { \
        printf("Running "#test"... "); \
        if (test()) { \
            printf("[OK]\n");\
        } else { \
                printf("[Failed]\n"); \
        } \
} while(0)
#endif /* TEST1_H_ */
==649== Memcheck, a memory error detector
==649== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==649== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==649== Command: ./mtm_test1
==649==
==649== error calling PR_SET_PTRACER, vgdb might block
Running testMapCreateDestroy... [OK]
==649== Invalid read of size 4
==649==    at 0x108F10: compareInts (test1.c:44)
==649==    by 0x108937: mapFind (map.c:321)
==649==    by 0x1089B6: mapContains (map.c:95)
==649==    by 0x108A2F: mapPut (map.c:108)
==649==    by 0x1090DE: testMapAddAndSize (test1.c:64)
==649==    by 0x109612: runTest1 (test1.c:128)
==649==    by 0x1087B7: main (main.c:5)
==649==  Address 0x418a150000000002 is not stack'd, malloc'd or (recently) free'd
==649==
==649==
==649== Process terminating with default action of signal 11 (SIGSEGV)
==649==  General Protection Fault
==649==    at 0x108F10: compareInts (test1.c:44)
==649==    by 0x108937: mapFind (map.c:321)
==649==    by 0x1089B6: mapContains (map.c:95)
==649==    by 0x108A2F: mapPut (map.c:108)
==649==    by 0x1090DE: testMapAddAndSize (test1.c:64)
==649==    by 0x109612: runTest1 (test1.c:128)
==649==    by 0x1087B7: main (main.c:5)
Running testMapAddAndSize... ==649==
==649== HEAP SUMMARY:
==649==     in use at exit: 80 bytes in 3 blocks
==649==   total heap usage: 7 allocs, 4 frees, 672 bytes allocated
==649==
==649== 8 bytes in 1 blocks are definitely lost in loss record 2 of 3
==649==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==649==    by 0x108889: mapCreate (map.c:44)
==649==    by 0x1090AB: testMapAddAndSize (test1.c:59)
==649==    by 0x109612: runTest1 (test1.c:128)
==649==    by 0x1087B7: main (main.c:5)
==649==
==649== LEAK SUMMARY:
==649==    definitely lost: 8 bytes in 1 blocks
==649==    indirectly lost: 0 bytes in 0 blocks
==649==      possibly lost: 0 bytes in 0 blocks
==649==    still reachable: 72 bytes in 2 blocks
==649==         suppressed: 0 bytes in 0 blocks
==649== Reachable blocks (those to which a pointer was found) are not shown.
==649== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==649==
==649== For counts of detected and suppressed errors, rerun with: -v
==649== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)