为什么我会收到 SIGABRT?
Why am I getting 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;
}
这运行得很好,但是在 之后 它实际上打印出了结果。这在我尝试过的任何其他情况下都没有发生。从调试会话中,我可以看到它在 print_arr
完成之前工作正常,但在 returns 到 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]
时访问分配的 space 的边界之外。但是,这导致的大问题是您正在向 arr
写入两个额外的元素,这也是未定义的行为。在这种情况下,这将破坏调用方 (main
) 中的堆栈,从而导致在 main
returns.
时崩溃
// 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;
}
这运行得很好,但是在 之后 它实际上打印出了结果。这在我尝试过的任何其他情况下都没有发生。从调试会话中,我可以看到它在 print_arr
完成之前工作正常,但在 returns 到 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]
时访问分配的 space 的边界之外。但是,这导致的大问题是您正在向 arr
写入两个额外的元素,这也是未定义的行为。在这种情况下,这将破坏调用方 (main
) 中的堆栈,从而导致在 main
returns.