繁体   English   中英

简单快速排序实现的分段错误

[英]Segmentation fault on simple quick sort implementation

所以我一直试图在 C 中创建一个通用的递归快速排序实现。为了它是通用的,我使用了一个比较函数指针。 此外,由于我们可以使用 Lomuto 或 Hoare 分区,我使用一个函数指针指向两个单独的函数,每个分区一个。 现在我只完成了 Lomuto 部分。 现在当然,比较函数不是用在快速排序函数本身中,而是用在分区函数上,所以我传递了函数指针。 应该很简单,但我迫切需要一些帮助,因为在尝试调用该函数时我不断收到分段错误:

quicksort_recursive(array, 0, 8, sizeof(int), &cmpnum, &partition_lomuto);

这是比较函数:

int cmpnum(const void* s1, const void* s2)
{
    int *a = (int*)s1;
    int *b = (int*)s2;
    if ((*a) > (*b))
        return 1;
    else if ((*a) < (*b))
        return -1;
    else
        return 0;
}

这是数组:

int array[] = [3, 7, 8, 5, 2, 1, 9, 5, 4];

肇事者在这里某处:

void swap(void *a, void *b, size_t size)
{
    char buffer[size];
    memcpy(buffer, a, size);
    memcpy(a, b, size);
    memcpy(b, buffer, size);
    return;
}

void *get(void *const array, size_t index, size_t size)
{
    return ((char *)array) + (index * size);
}

size_t partition_lomuto(void *const array, size_t low, size_t high, size_t size, __compar_fn_t compare)
{
    void *pivot = get(array, high, size);
    size_t i = low;
    for (size_t j = low; j <= high - 1; j++)
    {
        if(compare(get(array, j, size), pivot) <= 0)
        {
            i++;
            swap(get(array, i, size), get(array, j, size), size);
        }
    }
    swap(get(array, i + 1, size), get(array, high, size), size);
    return (i + 1);
}

void quicksort_recursive(void *const array, size_t low, size_t high, size_t size, __compar_fn_t compare, size_t (*partition)(void *const array, size_t low, size_t high, size_t size, __compar_fn_t compare))
{
    if (low < high)
    {
        size_t partition_index = partition(array, low, high, size, compare);
        quicksort_recursive(array, low, partition_index - 1, size, compare, partition);
        quicksort_recursive(array, low, partition_index + 1, size, compare, partition);
    }
    return;
}

使用gcc -fsanitize=address ...构建程序并运行它会导致以下错误:

=================================================================
==89==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff14f51124 at pc 0x7f766a029dd3 bp 0x7fff14f50f10 sp 0x7fff14f506c0
READ of size 4 at 0x7fff14f51124 thread T0
    #0 0x7f766a029dd2 in __interceptor_memcpy (/lib64/libasan.so.6+0x39dd2)
    #1 0x401381 in swap /tmp/t.c:19
    #2 0x401527 in partition_lomuto /tmp/t.c:44
    #3 0x401584 in quicksort_recursive /tmp/t.c:52
    #4 0x4018e0 in main /tmp/t.c:64
    #5 0x7f7669e4d1e1 in __libc_start_main (/lib64/libc.so.6+0x281e1)
    #6 0x4010dd in _start (/tmp/a.out+0x4010dd)

Address 0x7fff14f51124 is located in stack of thread T0 at offset 84 in frame
    #0 0x4015fc in main /tmp/t.c:60

  This frame has 1 object(s):
    [48, 84) 'array' (line 61) <== Memory access at offset 84 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/lib64/libasan.so.6+0x39dd2) in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x1000629e21d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000629e21e0: 00 00 00 00 ca ca ca ca 04 cb cb cb cb cb cb cb
  0x1000629e21f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000629e2200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000629e2210: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 f1 f1
=>0x1000629e2220: 00 00 00 00[04]f3 f3 f3 f3 f3 00 00 00 00 00 00
  0x1000629e2230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000629e2240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000629e2250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000629e2260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000629e2270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==89==ABORTING

看起来错误在这里:

    swap(get(array, i + 1, size), get(array, high, size), size);

虽然您知道i <= high ,但i + 1可能会越界。

PS 你有lowhigh作为包含(封闭)间隔。 If 通常更容易推理使用半开区间的算法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM