以下C代码中如何正确管理内存?

问题描述 投票:0回答:1

我最近开始学习 C 编程(我在 Python 方面有一些中级水平的经验(?))。我在 LeetCode 上看到了这个名为“两个排序数组的中位数”的问题,我想我可以尝试使用 C 实现该代码。该代码由三个函数组成,因为问题在于整个代码,特别是内存管理(?如果还有其他人请帮忙),我将发布整个内容。

int* insert(int* arr, int n, int x)
{
    int *ret = (int *) calloc(n+1,sizeof(int)), cont = 0;
    for(int i = 0; i<n && *(arr+i) < x; i++)
    {
        *(ret + i) = *(arr + i);
        cont++;
    }
    *(ret+cont) = x;
    for(int i = cont; i < n; i++)
    {
        *(ret+i+1) = *(arr + i);
    }
    return ret;
}
int* merge(int* arr1, int len1, int* arr2, int len2)
{
    int *ret = (int *) calloc(len1 + len2, sizeof(int)), **temp = (int **) malloc((len2+1)*sizeof(int *));
    for(int i = 0; i < len1; i++)
    {
        *(ret+i) = *(arr1+i);
    }
    *temp = ret;
    for(int i = 0; i < len2; i++)
    {
        *(temp+i+1) = insert(*(temp+i),len1+i, *(arr2+i));
    }
    for(int i = 0; i < len1+len2; i++)
    {
        *(ret + i) = *(*(temp+len2-1)+ i);
    }
    for(int i = 0; i < len2; i++)
    {
        free(*(temp+i));
    }
    free(temp);
    return ret;
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size)
{
    int *arr = merge(nums1, nums1Size, nums2, nums2Size), len = nums1Size+ nums2Size;
    double mid;
    if(len % 2 == 1)
    {
        mid = *(arr + len/2);
    }
    else
    {
        mid = (*(arr+len/2)+*(arr+len/2+1))/2.0;
    }
    free(arr);
    return mid;
}

合并和插入算法我相信插入排序的实现(?),我知道代码可以提高很多效率。但我的问题出在其他地方(?),LeetCode 上弹出以下错误消息:

=================================================================
==22==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000054 at pc 0x56200c01d257 bp 0x7fffc24d3340 sp 0x7fffc24d3330
READ of size 4 at 0x602000000054 thread T0
    #2 0x7f623c602082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
0x602000000054 is located 4 bytes inside of 12-byte region [0x602000000050,0x60200000005c)
freed by thread T0 here:
    #0 0x7f623d010537 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127
    #4 0x7f623c602082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
previously allocated by thread T0 here:
    #0 0x7f623d010a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
    #4 0x7f623c602082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00 fa fa fa 04 fa fa fa[fd]fd fa fa fd fd
  0x0c047fff8010: fa fa 00 04 fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==22==ABORTING

我认为这表明内存泄漏,尽管我根本不熟悉所以不能肯定地说。请查看代码和错误并建议如何克服这个问题。

我已经多次尝试纠正我认为的问题(例如最初只是

*temp
而不是
**temp = (int **) malloc((len2+1)*sizeof(int *))
,这是不可能解除分配的。但是问题仍然存在,我不知道该怎么办或搜索。任何帮助将不胜感激。谢谢!

c algorithm pointers memory-management dynamic-memory-allocation
1个回答
0
投票

*(ret + i) = *(*(temp + len2 - 1) + i);
中的
merge
函数访问数组越界`。它的作用与:

*( temp[len2 - 1] + i )

也就是说,它从

temp
数组中位置
len2 - 1
处获取值,并将其用作添加
i
的地址,然后取消引用。这具有未定义的行为,您的程序可能会崩溃,甚至更糟。

建议修复直接进行合并,而不必调用

insert
:

int* merge(int arr1[], int len1, int arr2[], int len2) {
    int * const ret = malloc((len1 + len2) * sizeof(int));
    int *wr = ret;

    // merge the two arrays while they both have values
    for(;len1 && len2; ++wr) {
        if(*arr1 < *arr2) {            
            *wr = *arr1++;
            --len1;
        } else {
            *wr = *arr2++;
            --len2;
        }
    }
    // here either len1 or len2 or both are zero

    // fill with any residue from arr1
    for(;len1; --len1) *wr++ = *arr1++;
    
    // fill with any residue from arr2
    for(;len2; --len2) *wr++ = *arr2++;
    
    return ret;
}

我还想总体上推广

pointer[index]
而不是
*(pointer + index)
。示例:

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
    int *arr = merge(nums1, nums1Size, nums2, nums2Size),
        len = nums1Size + nums2Size;

    double mid;
    if (len % 2 == 1) {
        mid = arr[len / 2];
    } else {
        mid = (arr[len / 2] + arr[len / 2 + 1]) / 2.0;
    }
    free(arr);
    return mid;
}
© www.soinside.com 2019 - 2024. All rights reserved.