簡體   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