c - 为什么我得到 SIGABRT?
问题描述
// Sort the given numbers in non decreasing order
// such that even and odd numbers are alternatively
// fit inside the array.
#include <stdio.h>
void swap(int* a, int* b)
{
int t;
t = *a;
*a = *b;
*b = t;
}
void sort(int* arr, int size)
{
int i, j;
for (i = 0; i < size - 1; ++i)
for (j = 0; j < size - i - 1; ++j)
if (arr[j] > arr[j + 1])
swap(arr + j, arr + j + 1);
}
void print_arr(int* arr, int size)
{
for (int i = 0; i < size; ++i)
printf("%d ", arr[i]);
printf("\n");
}
void rearrange(int* arr, int size)
{
// have two arrays to store odds and evens
int odds[size], evens[size];
int i, j, k;
// sort the array
sort(arr, size);
// populate the two arrays
for (i = 0, j = 0, k = 0; i < size; ++i)
{
if (arr[i] % 2) odds[j++] = arr[i];
else evens[k++] = arr[i];
}
print_arr(odds, j);
print_arr(evens, k);
// check the first elements of `odds` and `evens`
// in order to decide which ones occupy
// the odd and even indices
int* first;
int* second;
if (odds[0] < evens[0])
{
first = odds;
second = evens;
} else {
first = evens;
second = odds;
swap(&j, &k);
}
// populate the odd and even indices of `res`
i = 0;
while (j >= 0)
{
arr[i] = first[--j];
i += 2;
}
i = 1;
while (k >= 0)
{
arr[i] = second[--k];
i += 2;
}
}
int main()
{
int nums[] = { 80, 54, 0, 9, 6, 5, 4, 67, 1}; // SIGABRT
// int nums[] = { 80, 54, 9, 5, 4, 67, 1};
rearrange(nums, 9);
print_arr(nums, 9);
return 0;
}
这运行得很好,但在实际打印出结果后会抛出一个 SIGABRT。这在我尝试过的任何其他情况下都没有发生。从调试会话中,我可以看到它工作正常,直到完成print_arr
,但是在它返回到 之后main
,抛出一个 SIGABRT,那是在它实际将结果打印到控制台之后。我一直无法弄清楚为什么。
调试器输出:
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
frame #0: 0x0000000100000f01 odd_even`main at odd_even.c:89:5
86 int nums[] = { 80, 54, 0, 9, 6, 5, 4, 67, 1}; // SIGABRT
87 // int nums[] = { 80, 54, 9, 5, 4, 67, 1};
88 rearrange(nums, 9);
-> 89 print_arr(nums, 9);
90 return 0;
91 }
92
Target 0: (odd_even) stopped.
(lldb)
80 67 54 9 6 5 4 1 0
Process 2580 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff6be8249a libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
-> 0x7fff6be8249a <+10>: jae 0x7fff6be824a4 ; <+20>
0x7fff6be8249c <+12>: movq %rax, %rdi
0x7fff6be8249f <+15>: jmp 0x7fff6be7c3b7 ; cerror_nocancel
0x7fff6be824a4 <+20>: retq
Target 0: (odd_even) stopped.
你可以看到我确实得到了输出,但是在那之后得到了信号。
解决方案
当您填充 的奇数和偶数索引时res
,您的循环会在j
或k
为零时运行。这会导致分配arr[i] = first[--j];
和arr[i] = second[--k];
在访问元素first[-1]
和时访问分配空间的边界之外second[-1]
。但是,这导致的最大问题是您正在向 写入两个附加元素arr
,这也是未定义的行为。在这种情况下,这将破坏调用者 ( main
) 中的堆栈,从而导致main
返回时崩溃。
推荐阅读
- amazon-web-services - Amazon Appstream 2.0 桌面应用程序的性能测试
- sql - 远程服务器上的 SELECT @@ServerName 返回本地 @@ServerName
- php - 当我添加 Bootstrap 时,为什么我的导航栏文本会变高?
- javascript - 用 BeautifulSoup 抓取 fanduel,在 HTML 中找不到可见的值
- xamarin - 如何在 xamarin 表单中更改视觉材料 DatePickerDialog 和 TimePickerDialog 背景颜色
- amazon-web-services - AWS Redshift 创建一个存储过程来执行手动 vaccum
- graph-algorithm - 网络延迟问题 - 复杂性分析
- google-cloud-functions - 内存分配 google cloud 函数含义
- pem - (ssg-wsg) 没有起始行
- node.js - 如何在 mongodb 聚合中使用 $or 条件和 $geoNear