代码之家  ›  专栏  ›  技术社区  ›  aJ.

结构异常情况下的堆栈展开

  •  4
  • aJ.  · 技术社区  · 15 年前

    这个问题使所描述的问题更加清晰 here . 我做了更多的调查,发现在以下代码段中没有发生堆栈展开:

    class One
    {
    public:
        int x ;
    };
    
    class Wrapper
    {
    public:
        Wrapper(CString csText):mcsText(csText)
        {
            CString csTempText;
            csTempText.Format("Wrapper constructor :: %s\n", mcsText);
            OutputDebugString(csTempText);
        }
    
        ~Wrapper()
        {
            CString csTempText;
            csTempText.Format("Wrapper destructor :: %s\n", mcsText);
            OutputDebugString(csTempText);
        }
        CString mcsText;
    };
    class Test
    {
        public:
    
        void notifyError()
        {
            try
            {
                int x = 10; 
            }
            catch(...)  {}
        }
    
        void OnRecvBuffer()
        {
            try
            {
                Wrapper a("AddRef");    
                One* p = NULL;
                p->x = 10;
            }
            catch(...)
            {
                notifyError();
            }   
        }   
    };
    
    
    
    int main() 
    {
        Test* pTest = new Test;
    
        pTest->OnRecvBuffer();
    
        OutputDebugString("Test");
    }
    

    我使用VC6 SP5编译器编译了这段代码,输出为“Wrapper constructor::AddRef!!!”(即,未调用在堆栈上构造的Wrapper对象的析构函数。这是预期的行为吗?还是VC编译器的错误?我是否可以使用一些编译器标志以便在这种情况下展开堆栈?

    4 回复  |  直到 7 年前
        1
  •  7
  •   John Kugelman Michael Hodel    15 年前

    _set_se_translator() . 问题是,您可以捕获Win32异常,但堆栈将无法正常展开。至少你不能把你的生命押在这上面。这项运动的徒劳之处就在于此。

    如果是这样的话,不要这样做。有比通过未定义的行为更好的方法抛出异常。

    例如:

    void OnRecvBuffer()
    {
        try
        {
            Wrapper a("AddRef");    
            throw 42; // this'll throw an exception without invoking UB
        }
        catch(...)
        {
            notifyError();
        }
    }
    

    One* p = NULL;
    p->x = 10;
    

    能够

    p 是指向 One 对象它应该包含一个 对象您已将其初始化为0--地址0处没有对象。0不是任何对象的有效地址(这由标准保证)。

        2
  •  4
  •   Evgeny Lazin    15 年前

        3
  •  2
  •   Gregor Brandt    15 年前

        4
  •  0
  •   Loki Astari    15 年前

    这是未定义的行为:

    One* p = NULL;
    p->x = 10;
    


     throw 42; // Life the Universe and Everything thrown away
    

    你不应该动态分配你的所有对象,这是C++,而不是java!

    int main() 
    {
        Test    pTest;   // Note the lack of new!
    
        pTest.OnRecvBuffer();
    
        OutputDebugString("Test");
    }