首页 > 解决方案 > 为什么我得到 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.

你可以看到我确实得到了输出,但是在那之后得到了信号。

标签: csigabrt

解决方案


当您填充 的奇数和偶数索引时res,您的循环会在jk为零时运行。这会导致分配arr[i] = first[--j];arr[i] = second[--k];在访问元素first[-1]和时访问分配空间的边界之外second[-1]。但是,这导致的最大问题是您正在向 写入两个附加元素arr,这也是未定义的行为。在这种情况下,这将破坏调用者 ( main) 中的堆栈,从而导致main返回时崩溃。


推荐阅读