通过P / Invoke防止在应用程序调用库中发生无优雅崩溃

时间:2013-02-06 19:08:33

标签: c# c++

我有一个C#应用程序App A,通过P / Invoke调用C ++(Qt)DLL App B。我们假设我不能以任何方式编辑App B,但我知道App B在一组条件下抛出Out of Memory Exception我可以复制但在传递输入之前没有准确测试从App AApp B。此异常不会对App A造成任何威胁,如果App B可以某种方式“重置”,则可以忽略此异常,但当App B崩溃时,它会调用abort()导致App A的运行时终止。

如何阻止App B不可避免,不可预测且普遍平凡的崩溃影响App A

注意:

  • 抛出此错误时,将忽略已实现的UnhandledExceptionHandler
  • App B由于QtWebkit中的错误导致崩溃,App B可以通过删除超大对象并返回null来处理。
  • App A没有报告为内存不足,并且机器有足够的内存来执行App B的操作多次,无论错误如何,但是这个内存显然没有分配无论出于什么原因,App B。{/ li>

2 个答案:

答案 0 :(得分:3)

您创建了一个填充程序,其唯一目的是加载App B并使用某种IPC机制与App A进行通信.App A生成填充程序,如果填充程序崩溃,则App A采取相应的操作(重新生成,传达错误)对用户等。)。

答案 1 :(得分:1)

你可以处理来自非托管代码的SIGABRT,但它有点乱。它可以在C#中完全完成,但是我的方法需要一个C ++ / CLI程序集来使它工作(至少它只在一个进程中)。

步骤1:创建一个C ++ / CLI类库项目,在* .h文件中放入以下函数

namespace ClassLibrary1 {

    public ref class Class1
    {
    public:
        static void callaborter();
    };
}

步骤2:在cpp文件中输入以下代码:

// This is the main DLL file.

#include "stdafx.h"
#include <csetjmp>
#include <csignal>
#include <cstdlib>
#include <iostream>
#include "ClassLibrary1.h"
#include "..\Win32Project1\Win32Project1.h"


#pragma managed(push, off) 
jmp_buf env;

void on_sigabrt (int signum)
{
    longjmp (env, 1);
}

void run()
{
    if (setjmp (env) == 0) {
            signal(SIGABRT, &on_sigabrt);
            fnWin32Project1();
    }
    else {
            std::cout << "aborted\n";
    }
}

#pragma managed(pop)

void ClassLibrary1::Class1::callaborter()
{
    run();
}

我将我的类库和类的名称保留为默认值,我的中止函数是调用fnWinProject1()。您需要将有问题的DLL直接链接到此项目(就像它在C ++中一样)

在C#类中,包含对C ++ / CLI程序集的引用,并调用“callaborter”方法。

运行中的代码将为SIGABRT设置捕获器(由abort()调用)并在on_sigabrt()中处理它,这将导致整个函数保释。然后,您可以清理并重试。

我会留下它作为OP的练习,以选择有用的名字。

注意:在Debug中,您仍然会看到中止对话框,只需按Ignore继续。在发布中,您将看不到对话框。

P.S。我应该提一下,我根据这个stackoverflow问题构建了我的响应:How to Handle SIGABRT signal?

相关问题