0

在下面的代碼中,我在python模塊代碼中使用try/catch。在try塊中,我有一個簡單的錯誤(內存訪問衝突),並試圖捕獲相應的異常並安靜地終止程序,而不生成.stackdump文件。然而,後者仍然生成暗示try/catch構造不能完成它的工作。我怎樣才能避免生成.stackdump文件並在不正確的操作(如代碼中的一個)得到滿足時退出程序? P.S.我正在編制在Cygwin中的代碼用gcc和Boost.Python的嘗試/趕上,以避免.stackdump

有趣的是,它沒有的情況下,僅x[3]=2工作,而是適用於所有其他情況:例如x[4]=2x[20]=2,或者顯然,x[2]=2

#include <boost/python.hpp> 
#include <iostream> 
#include <iomanip> 
using namespace std; 
using namespace boost::python; 


class Hello 
{ 
    std::string _msg; 

public: 

    Hello(std::string msg){_msg = msg;} 

    void run(){ 
     try{ 

     double* x; 
     x = new double[3]; 
     x[3] = 2.0; 
     delete [] x; 


     }catch(...){ exit(0); } 

    } 

}; 


BOOST_PYTHON_MODULE(xyz) 
{ 
    class_<Hello>("Hello", init<std::string>()) 
     .def("run",&Hello::run) 
    ; 

} 

編輯:

根據什麼Maciek曾建議我嘗試以下竅門:

進行信號處理函數拋出一個異常,但不退出

void sig_action(int signo) { 
    std::cout << "SIGNAL " << signo << std::endl; 
    throw 1; 
// exit(0); 
} 

現在嘗試在try/catch塊中放置一個可能有問題的函數(信號函數放在類構造函數中):

class Hello 
{ 
    std::string _msg; 

public: 

    Hello(std::string msg){ 
    _msg = msg; 
     signal(SIGABRT, sig_action); 
     signal(SIGSEGV, sig_action); 

    } 
    void set(std::string msg) { this->_msg = msg; } 
    std::string greet() { return _msg; } 

    void run(){ 

     try{ 
     double* x; 
     x = new double[3]; 
     x[3] = 2.0; 
     delete [] x; 

     }catch(...){ cout<<"error in function run()\n"; exit(0); } 

    } 

}; 

但是這樣一招行不通,因爲我希望它產生以下輸出:

SIGNAL 6 
terminate called after throwing an instance of 'int' 
SIGNAL 6 
terminate called recursively 
SIGNAL 6 
terminate called recursively 
.... 
(and many more times the same) 

所以拋出異常,但它已被抓之前一切結束。有什麼辦法讓它在終止這個過程之前被抓到?

回答

1

您只能捕獲拋出的異常。無效的指針訪問不會引發異常,它只會導致未定義的行爲,並且在您的特定情況下會導致堆棧轉儲。

如果您想要了解這種情況,請使用std::vectorat function訪問項目。當與無效索引一起使用時,這將拋出std::out_of_range。但是,通常最好先避免這種訪問的可能性,因爲它們通常指示程序中的錯誤,並且錯誤不應該通過例外來處理,它們應該從代碼中移除。

+0

謝謝。事實上,這就是我如何找到一個錯誤 - 通過找到引發異常的代碼(很可能是內存訪問的一些問題)的一部分。我知道這不是應該如何找到一個錯誤,但它是我目前唯一的方式 - 它的一個長長的故事。我還添加了一些更正 - 似乎仍然拋出異常,但不是所有情況下;但在其中大部分。 – user938720 2013-03-24 21:07:35

1

在Linux上,核心轉儲由信號處理程序生成,默認操作設置爲coreSIGABRTSIGSEGV,...)。如果你想避免核心轉儲,你總是可以捕獲/忽略這些信號。它也應該在Cygwin stackdumps上工作。但是你仍然可能會得到一些令人討厭的消息作爲輸出。

編輯:

#include <signal.h> 

// [...] 

void sig_action(int signo) { 
    std::cout << "SIGNAL " << signo << std::endl; 
    exit(0); 
} 

int main(int argc, char* argv[]) { 
    signal(SIGABRT, sig_action); 
    signal(SIGSEGV, sig_action); 

    Hello h("msg"); 
    h.run(); 
} 
+0

不知道如何使用它。你能否提供一些細節如何在代碼中包含這些內容(例如,例子中的那個)? – user938720 2013-03-24 22:45:14

+0

我已經添加了一個示例代碼。如果您只是想忽略該信號,請使用'SIG_IGL'作爲動作功能 – 2013-03-24 22:56:42

+0

謝謝Maciek。這是一般工作,但它是否有可能檢查代碼的哪一部分出現問題?例如,讓我們說我們有另一個沒有錯誤的函數run1(比如在原始運行中)並調用這兩個函數。在信號使用的基礎上,我怎麼知道哪一個會導致這個問題呢?使用try/catch構造,可以將每個函數括起來並區分哪一個包含錯誤。是否有可能做這樣的信號功能? – user938720 2013-03-24 23:12:08