地址消毒堆在释放后使用

address sanitizer heap use after free

我正在尝试解决这个问题 “给定一个整数数组 nums 和一个整数目标,return 两个数字的索引使得它们加起来等于目标。” 这段代码工作正常,并在我的本地机器上给出了正确的输出,但这在 leet 代码中不起作用。 当我在 leet 代码中 运行 它时,我收到错误消息:AddressSanitizer heap-use-after-free。 我无法弄清楚我到底在哪里使用了超出范围的内存。

typedef struct entries
{
    int val;
    int index;

}entry_t;

typedef struct table
{
    entry_t *entry;
}ht_t;

ht_t *table;

int hash(int key, int size)
{
    int slot = key % size;
    return slot < 0 ? (slot + size) : slot;
}
void insert(int key, int index, ht_t *table, int size)
{
    int slot;
    slot = hash(key, size);

    table->entry[slot].val = key;
    table->entry[slot].index = index;
}

int *search(int key, int num, ht_t *table, int size)
{
    int slot;
    slot = hash(key, size);
    if(table->entry[slot].val == key)
    {
        return &(table->entry[slot].index);
    }
    return NULL;

}


int* twoSum(int* nums, int numsSize, int target, int* returnSize){

    int i;
    *returnSize = 2;
    int *returnArr= (int*) malloc((2)*sizeof(int));
    //int i;
    int complement;
    int *retVal;
    //int size =  numsSize;
    table = (ht_t *)malloc(sizeof(ht_t)*1);
    table->entry =  malloc(sizeof(entry_t)*100);

    for(i=0; i<numsSize; i++)
    {
        complement = target - nums[i];
        // look for the other number
        retVal = (search(complement,nums[i], table, numsSize));
        if(retVal != NULL)
        {
            returnArr[0] = *retVal;
            returnArr[1] = i;
            break;
        }
        // if not found insert it to the table.
        insert(nums[i],i,table, numsSize);

    }
    free(table);
    free(table->entry);
    return returnArr;
    
}

int main(void) {
    //int arr[6] = {1,2,3,8,5,6};
    int arr[6] = {2,7,11,15};
    int target = 9;
    int* indices = malloc(sizeof(int)*2);;
    indices = twoSum(arr, 4, target, indices);
    printf("index1 = %d, index2 = %d\n",indices[0], indices[1]);
    free(indices);
}
free(table);
free(table->entry);

交换这些语句。 您首先释放 table 的内存,然后访问 table ==> 错误。

举个例子运行 它与 valgrind (valgrind ./executable)

==3028== Memcheck, a memory error detector
==3028== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3028== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==3028== Command: ./a.out
==3028== 
==3028== Conditional jump or move depends on uninitialised value(s)
==3028==    at 0x109218: search (c.c:35)
==3028==    by 0x1092E1: twoSum (c.c:60)
==3028==    by 0x1093D5: main (c.c:82)
==3028== 
==3028== Invalid read of size 8
==3028==    at 0x109358: twoSum (c.c:72)
==3028==    by 0x1093D5: main (c.c:82)
==3028==  Address 0x4a0f0e0 is 0 bytes inside a block of size 8 free'd
==3028==    at 0x48399AB: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==3028==    by 0x109350: twoSum (c.c:71)
==3028==    by 0x1093D5: main (c.c:82)
==3028==  Block was alloc'd at
==3028==    at 0x483877F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==3028==    by 0x109272: twoSum (c.c:53)
==3028==    by 0x1093D5: main (c.c:82)
==3028== 
index1 = 0, index2 = 1
==3028== 
==3028== HEAP SUMMARY:
==3028==     in use at exit: 8 bytes in 1 blocks
==3028==   total heap usage: 5 allocs, 4 frees, 1,848 bytes allocated
==3028== 
==3028== LEAK SUMMARY:
==3028==    definitely lost: 8 bytes in 1 blocks
==3028==    indirectly lost: 0 bytes in 0 blocks
==3028==      possibly lost: 0 bytes in 0 blocks
==3028==    still reachable: 0 bytes in 0 blocks
==3028==         suppressed: 0 bytes in 0 blocks
==3028== Rerun with --leak-check=full to see details of leaked memory
==3028== 
==3028== Use --track-origins=yes to see where uninitialised values come from
==3028== For lists of detected and suppressed errors, rerun with: -s
==3028== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

你得到了这个输出。它告诉你什么? 您在第 53 行分配了一个大小为 8 的块,您在第 71 行释放了它并尝试在第 72 行访问它。

(另外,您在第 35 行使用了未初始化的值)。