【问题标题】:Compare Integers Function SIGSEGV比较整数函数 SIGSEGV
【发布时间】:2014-12-27 00:27:08
【问题描述】:

这是我的比较函数:

int compareInts(const void *a, const void *b) {
    const int *pa = (const int*)a;
    const int *pb = (const int*)b;
    return *pa - *pb;
}

当我将此函数与整数数组一起传递给 qsort 时:

qsort(a, size, sizeof(char*), compareInts);

一切正常,我得到一个排序列表。但是,如果我自己尝试使用它:

compareInts(2, 2);

除非我修改函数如下:

int compareInts(const void *a, const void *b) {
    const int *pa = (const int*)a;
    const int *pb = (const int*)b;
    return pa - pb;
}

当我调用它时效果很好,但是当传递给 qsort 时会返回一个未排序的列表! 这是怎么回事?

【问题讨论】:

  • qsort() 的第三个参数是每个元素的大小。如果您实际上是在对 int 的数组进行排序,那么第三个参数应该是 sizeof(int) 或者可能是 sizeof(*a)
  • '2' 不是指针,该函数需要两个指针。所以它认为'2'是一个指针并将其视为指针。访问超出进程数据限制的地址 2 会导致未定义的行为,从而导致段错误事件。该程序的第二个版本是比较指针,而不是指针指向的内容。

标签: c function integer compare qsort


【解决方案1】:

试试这个:

int a=2;
int b = 2;
compareInts(&a, &b);

您的比较函数直接接受指针,而不是整数。 当你传入两个整数时会发生什么

compareInts(2,3);

你是在告诉这个函数去分别在内存地址 0x00000002 和 0x00000003 找到你的整数,而这些不是有效地址。

在您修改后的函数中,您比较两个指针 0x00000002 和 0x00000003 的值,而不尝试取消引用它们,因此它不会崩溃。

【讨论】:

  • "没有尝试取消引用它们" --> 应该是"没有在你的调用中传递它们的 地址,而不是仅仅传递原始值 "2"(即 值存储在该地址中)。您的函数需要一个地址。OP的问题发生特别是因为他/她尝试取消引用它们。
  • 在您修改后的函数中,您正在比较指针中的值。另一方面,qsort 一次传递两个值以正确地 compareInts,这意味着它执行类似于 compareInts(&arr[i], &arr[j]) 的操作,因此它可以工作。 qsort 不关心 compareInts 对这些值做了什么——它只需要一个整数结果。如果您将修改后的函数与 qsort 一起使用,您将比较内存地址而不是值。
【解决方案2】:

使用此代码:

compareInts(2, 2);

您正在尝试将内存位置 2 与内存位置 2 进行比较。这将给您带来段冲突,因为您无权访问内存位置 2。您没有尝试比较两个 位于您可以访问的内存地址 - 在操作系统意识到您无权访问这些位置之前,您甚至无法到达该位置(并给您一个很大的 SEGV 感谢您尝试)。您需要比较您实际有权访问的内存地址的内容。例如:

  int a = 2;   // a is an integer variable, you can take the address of this
  int b = 2;   // ibid

  compareInts(&a, &b);  // now, you are giving your function *the addresses of* a and b

【讨论】:

  • 与@DNT 重叠——如果你要接受其中一个作为答案,请以他的——慢打字日为我。
猜你喜欢
  • 2017-02-11
  • 1970-01-01
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
  • 2013-08-24
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多