leetcode C中合并排序数组编译报错

Merge Sorted Array in leetcode C Compile error

我正在尝试解决 this LeetCode problem

You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n, representing the number of elements in nums1 and nums2 respectively.

Merge nums1 and nums2 into a single array sorted in non-decreasing order.

The final sorted array should not be returned by the function, but instead be stored inside the array nums1. To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, and the last n elements are set to 0 and should be ignored. nums2 has a length of n.

Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]

我下面的解决方案在我的 Mac 上的 vscode 上运行良好,但是当我 运行 它在 leetcode 上使用完全相同的测试用例时,它会抛出编译错误。有人知道为什么吗?

/// my solution
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int i = m - 1;
    int j = n - 1;
    int k = nums1Size - 1;

    while(k >= 0){
        if (nums1[i] < nums2[j]){
            nums1[k--] = nums2[j--];
        } else {
            nums1[k--] = nums1[i--];
        }
    }
}

int main(void){
    int arr1[] = {1, 2, 3, 0, 0};
    int arr2[] = {5, 6};
    merge(arr1, 5, 3, arr2, 2, 2);
    for (int i = 0; i < 5; i++){
        printf("%i\n", arr1[i]);
    }
}

此代码正确打印 1,2,3,5,6。

但是在 leetcode 上,当我给出相同的输入时,它显示

==31==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000000c at pc 0x564b115dfc07 bp 0x7ffecbbcf300 sp 0x7ffecbbcf2f0
READ of size 4 at 0x60200000000c thread T0
    #2 0x7f4f899f30b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
0x60200000000c is located 4 bytes to the left of 8-byte region [0x602000000010,0x602000000018)
allocated by thread T0 here:
    #0 0x7f4f8a638bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #3 0x7f4f899f30b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
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 fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa 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
==31==ABORTING

想象一下这样的情况:

nums1 = {10, 11, 12, 0, 0, 0};   
nums2 = {1, 2, 3};

在 while 循环中的某个时刻索引 i 将变为 -1 并且索引 j 将变为 2,您将比较 nums1[-1] and nums2[2] 这导致一个错误。而且您还忘记了在 while 循环之后可能有一些元素没有插入到 nums1 中。我认为这段代码将帮助您更好地理解:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int i = m - 1, j = n - 1, k = nums1Size - 1;

    while(i >= 0 && j >= 0){
        if (nums1[i] < nums2[j]){
            nums1[k--] = nums2[j--];
        } else {
            nums1[k--] = nums1[i--];
        }
    }

    while (i >= 0) nums1[k--] = nums1[i--];
    while (j >= 0) nums1[k--] = nums2[j--];
}

我建议你在纸上执行你的代码,看看错误在哪里。