从c#捕获本机异常并在其离开作用域后获取异常.what()
我从C#Mono调用一个本机dll,但我无法用try-catch子句C#side捕获异常。显然,Mono不支持这一点,不管设置了什么标志(根据其他关于这个问题的帖子)。Mono总是在异常离开本机端时关闭 我提出的解决方案是,用c#中的所有dll外部方法传递一个从c#捕获本机异常并在其离开作用域后获取异常.what(),c#,c++,exception,interop,marshalling,C#,C++,Exception,Interop,Marshalling,我从C#Mono调用一个本机dll,但我无法用try-catch子句C#side捕获异常。显然,Mono不支持这一点,不管设置了什么标志(根据其他关于这个问题的帖子)。Mono总是在异常离开本机端时关闭 我提出的解决方案是,用c#中的所有dll外部方法传递一个[Out]IntPtr errorText。这是作为字符**接收的本机端。本机C++函数将所有的内容打包在尝试catch(const STD::Extand EX)< /Cord>子句中。如果没有异常,我将errorText设置为nullp
[Out]IntPtr errorText
。这是作为字符**接收的本机端。本机C++函数将所有的内容打包在<代码>尝试catch(const STD::Extand EX)< /Cord>子句中。如果没有异常,我将errorText设置为nullptr,但如果有异常,我将其设置为*errorText=ex.what()
当本机调用返回时,它或者有一个指向error的null指针,这意味着没有异常,或者它是非null的,在这种情况下,我将其提取为Marshal.PtrToStringAnsi(errorText)
这是可行的,也不可行。捕获异常并设置指针,但封送处理调用从IntPtr返回null。经过一些测试后,我意识到如果我将本机错误文本指针设置为一个常量,如*errorText=“a test”
,那么它就会正常工作
问题似乎是,当本机函数返回时,本机异常对象超出范围,此时what()
文本无效,这意味着当我试图封送指向它的指针的内容时,它无效
一种解决方案是,我自己总是将常量字符串作为异常抛出,比如抛出“不好的东西”
并捕获它,因为这些常量字符串仍然有效,然后捕获其他std::exception
s只返回一个通用错误字符串,比如“undefined std::exception”
这显然不是完美的,尽管它可以工作。问题是为什么我在离开函数后无法访问*what()
。虽然实际的异常对象可能超出范围,但创建它时使用的消息本身通常是常量。如果我抛出std::exception(“something”)
那么what
应该指向常量“something”,并且在异常超出范围后应该保持有效
我曾考虑在dll中创建一个持久化的字符数组,并将what()复制到其中以供以后检索,但我需要支持多个同时访问,这可能会同时出现多个异常,从而导致t争夺此缓冲区
我非常感兴趣的是,如果有人对异常离开作用域后为什么what()
不可用有所了解,或者是一个比抛出字符串异常更优雅的解决方法
编辑:另一种解决方案是为错误消息管理端分配字符串,并传递指向该字符串的指针,以便本机端将错误放入其中。我只是不需要每次调用都分配一个新字符串。。。您更希望只在what()中获取一个指向实际消息的指针,您可以为“errorText”参数分配一个字符缓冲区(在本机DLL中),并将文本“ex.what()”复制到该缓冲区。在这种情况下,内存将保持有效。
但我认为,在读取C#中的字符串后,您必须自己释放char缓冲区,以防止内存泄漏。可能相关。()可能是解决方案:()这看起来确实相关,但我不能从我的本机代码中抛出异常,就像在引用的文章中一样。这会导致即时终止,而且我也无法分配从本机代码中为消息收集的垃圾。。。这是纯C++,没有MS的添加。不过,给我一个主意吧,所以我会延长我的职位。我很好奇为什么这次投票被否决了。这似乎是一个没有简单解决方案的一般问题…?谢谢,但根据我的问题,我已经考虑并拒绝了。我对你的回答有点不公平,因为你实际上没有说缓冲区应该在所有通话中共享。我现在使用的解决方案是为每个异常分配缓冲区,并将指针传递回托管。然后,Managed的任务是在读取文本后调用该指针上的本机delete。因此,我显然应该接受你的回答。如果我一开始误解了你,很抱歉。