[英]Pointers to pointers segmentation fault
我创建了一个插入排序方法,该方法接受一个数组,其大小和一个比较器。 比较器功能是这样的:
int compare_int_ptr(void* ptr1, void* ptr2) {
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
if(i1<i2) {
return -1;
}
if(i1 == i2) {
return 0;
}
return 1;
}
插入是这样的:
void insertion_sort(void** array, int size, CompFunction compare){
int i,j;
void* key;
for(i = 1; i<size;i++){
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
swap(&array[j+1],&array[j]);
}
array[j+1] = key;
}
}
如果尝试执行它,则会遇到分段错误错误,因此我认为我没有正确使用指针。 进行交换时我将&传递给我,是否正确?
编辑:这是我调用方法的地方:
int main(int argc, char const *argv[]) {
if(argc < 2) {
printf("Usage: sortingfirstusage <file_name>\n");
exit(EXIT_FAILURE);
}
double* array = load_array(argv[1]);
insertion_sort((void**)array, 3, compare_int_ptr);
free(array);
return 0;
数组已正确加载,因为在调用插入排序之前我已打印了所有元素,并且它们已插入。
您正在尝试对双打数组进行排序。 double *array
指向n
元素的第一个:
array ==> [ double ] \
[ double ] |
. > n elements
. |
[ double ] /
您正在将array
转换为void **
:
(void **)array ==> [ void * ] \
[ void * ] |
. > n elements
. |
[ void * ] /
不难确定问题就在眼前。 void *
不是double
。 它的大小可以与double
相同,也可以不相同。 它几乎肯定没有指向有效的内存位置,因此,如果取消引用它,则会调用未定义的行为 ,几乎可以肯定会导致您的程序被信号杀死。 不幸的是,您的insertion_sort
函数在调用比较函数时确实取消了对它的引用:
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
array[i]
和array[j]
都是无效的void *
值(因为基础内存包含double
,而不是void *
s)。 您的比较函数在这里取消引用它们:
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
ptr1
和ptr2
包含无意义的指针值。 它们不指向double
。 取消引用它们会调用未定义的行为 。
下面是一个工作版本insertion_sort
使用相同的功能的类型和等效的功能到qsort
从C标准库函数(尽管功能是很多小于高效qsort
):
insert_sort.h :
#ifndef INSERTION_SORT_H_INCLUDED__
#define INSERTION_SORT_H_INCLUDED__
#include <stddef.h>
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
#endif
insert_sort.c :
#include <string.h>
#include "insertion_sort.h"
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
char (*b)[size] = base;
size_t i;
size_t j;
int cmp;
for (i = 1; i < nmemb; i++) {
j = i - 1;
/* search backwards for insertion point */
while ((cmp = compar(b + j, b + i)) > 0 && j > 0)
j--;
if (cmp <= 0)
j++; /* went back one too far */
if (j < i) {
/* rotate element i to position j, j to j+1, ..., i-1 to i */
char tmp[size];
memcpy(&tmp[0], &b[i][0], size);
memmove(&b[j + 1][0], &b[j][0], size * (i - j));
memcpy(&b[j][0], &tmp[0], size);
}
}
}
这是上述功能的用法示例:
main.c :
#include <stdio.h>
#include "insertion_sort.h"
int compar_double(const void *a, const void *b)
{
double d1 = *(const double *)a;
double d2 = *(const double *)b;
if (d1 < d2)
return -1;
if (d1 > d2)
return 1;
return 0;
}
void print_doubles(const double *d, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
printf("%g\n", d[i]);
}
int main(void)
{
double numberlist[] = { 3.0, 1.0, 5.0, -4.0, 2.0 };
size_t len = sizeof numberlist / sizeof numberlist[0];
printf("Unsorted:\n");
print_doubles(numberlist, len);
printf("\n");
insertion_sort(numberlist, len, sizeof numberlist[0], compar_double);
printf("Sorted:\n");
print_doubles(numberlist, len);
return 0;
}
这是上述程序产生的输出:
Unsorted:
3
1
5
-4
2
Sorted:
-4
1
2
3
5
void qsort( void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
与qsort一样,您的排序函数应将void *
作为第一个参数,而不是void **
。 双间接的是,拨打电话时,你应该已经注意到一个错误insertion_sort
。 将double[]
数组转换为void **
需要强制转换,而可以将其自动转换为void *
而无需一个。
不知道是什么load_array(argv[1]);
确实,答案无法像彼得在评论中建议的那样预测。
假设此函数调用在做合法的事情,并使用可以正确取消引用的指针加载数组,那么您的问题就是强制转换。 您不能将指针变成指向指针的指针。 您必须传递指针的地址才能完成所需的操作。
insertion_sort(&array, 3, compare_int_ptr);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.