我有一个C#应用程序App A
,通过P / Invoke调用C ++(Qt)DLL App B
。我们假设我不能以任何方式编辑App B
,但我知道App B
在一组条件下抛出Out of Memory Exception
我可以复制但在传递输入之前没有准确测试从App A
到App 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>
答案 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?