【问题标题】:address sanitizer heap use after free释放后的地址消毒剂堆使用
【发布时间】:2021-03-07 14:03:16
【问题描述】:

我正在尝试解决这个问题 “给定一个整数数组 nums 和一个整数目标,返回两个数字的索引,使它们加起来为目标。” 这段代码工作正常,并在我的本地机器上给出了正确的输出,但这在 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);
}

【问题讨论】:

    标签: arrays c pointers hashtable


    【解决方案1】:
    free(table);
    free(table->entry);
    

    交换这些语句。 您首先释放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 行使用了未初始化的值)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-06
      • 2016-07-28
      • 1970-01-01
      • 2017-09-17
      • 2023-03-23
      • 2019-09-05
      • 1970-01-01
      • 2021-02-08
      相关资源
      最近更新 更多