簡體   English   中英

工作者線程堆棧溢出時的信息出口

[英]Informative exit on stack overflow in worker thread

我正在編寫一個C ++程序,該程序將在遞歸數據上運行一堆工作線程,這樣,即使我增加了默認的堆棧空間,線程也有可能遇到堆棧溢出。

理想的做法是使堆棧根據需要動態擴展,但是如果不可能,則可以使程序失敗,並讓用戶在使用較大的堆棧大小重新編譯后重試。

程序默認行為崩潰而沒有任何錯誤消息的問題是用戶無法知道問題出在哪里或如何解決。 就用戶所知,該程序可能試圖除以零或取消引用空指針; 因此,如果程序必須崩潰,我希望它首先將“ Stack Overflow”打印到stderr。

顯然,在便攜式C ++中不會有一種解決方案,但是我對一種適用於Windows的解決方案和另一種適用於Linux的解決方案感到滿意。

在尋找使程序在Windows上退出並顯示提示性錯誤消息的方法時,我一直在閱讀有關矢量化和結構化異常處理的文檔。 一個問題是它們似乎是線程本地的,並且線程不能安全地寫入stderr。 最好情況下,您會遇到種族問題。

有已知的處理方法嗎?

該操作系統(至少具有Linux或Unix風格)使您能夠捕獲堆棧故障。

像這樣:

 // Note: Calling printf here is probably not a brilliant idea, 
 // as we're in a signal handler. It is NOT well-defined what happens.
 void handler(int arg)
 {
    fprintf(stderr, "Crashed due to signal handler\n"); 
    exit(42);
 }

然后主要是這樣的...

 struct sigaction sa = { handler, NULL, 0, 0, NULL };
 struct sigaction oldsa;
 sigaction(SIGSTKFLT, sa, oldsa);

我將嘗試提出一些“完整”的解決方案,並進行一些實驗。

(我相信可以替換堆棧,但我認為您不能以有意義的方式實際上繼續執行該操作,而只是讓您以比崩潰更明智的方式恢復!)

這似乎可以正常工作:

#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <cstdlib>

void handler(int arg)
{
    write(2, "stack overflow\n", 15);
    _exit(42);
}

void* duh(void *arg)
{
    if(duh(arg))
    {
        return duh(NULL);
    }
    else
    {
        return duh(arg);
    }
}

void* crash_wrapper(void *arg)
{
    static char stack[SIGSTKSZ];
    stack_t ss = {};
    ss.ss_sp = stack;
    ss.ss_size = SIGSTKSZ;
    sigaltstack(&ss, 0);

    struct sigaction sa = {};
    sa.sa_handler = handler;
    sa.sa_flags = SA_ONSTACK,
    sigfillset(&sa.sa_mask);
    sigaction(SIGSEGV, &sa, 0);

    return duh(arg);
}

int main()
{
    pthread_t t;
    int status = pthread_create(&t, 0, crash_wrapper, 0 );

    for(;;)
    {
        std::cout << "Still going..." << std::endl;
        sleep(1);
    }
}

我對處理程序中的write不完全滿意,但是我嘗試過的所有其他方法似乎也不起作用... :(

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM