[英]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 你有low
和high
作為包含(封閉)間隔。 If 通常更容易推理使用半開區間的算法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.