Valgrind:大小为4的无效读取,1个块中的8字节在C中的丢失记录中肯定丢失
我正在尝试使用以下代码在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
#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)