预防 C++内部使用 try catch 的 DLL 异常
我正在开发一个 C++ DLL,为主应用程序分配一个数组。 该函数返回错误代码,而不是指向新创建的数组的指针,因此第一个成员的地址将写入函数的参数中。 示例:
int foo(int** arrayPtr) {
int* array = new int[10];
*arrayPtr = array;
return 0;
}
因此,在 main 中我这样调用该函数:
int* myArray;
int ret;
ret = foo(&myArray);
现在 myArray 指向新创建的数组。
问题1:有更好的方法吗?
比这个更有趣的问题。 如果我将 NULL 作为 foo 的参数传递,则会生成访问冲突异常,因为
*arrayPtr = array;
将尝试写入 0x00000。
所以,我添加了一个 try-catch 块
int foo(int** arrayPtr) {
int* array = new int[10];
try {
*arrayPtr = array;
} catch(...) {
return 1;
}
return 0;
}
,我希望当我使用 NULL 作为参数调用 foo 时,它将返回 1。不正确!它会产生异常。
问题 2:为什么 DLL 中的 try-catch 块不起作用?
谢谢大家!
PS:使用 try-catch 直接在 main 中生成相同的异常不会生成异常(或者更好,它由 try-catch 块正确处理)。
I'm developing a C++ DLL that allocate an array for the main application.
The function return an error code and not the pointer to the new created array, so the address of the first member will be written in a parameter of the function.
Example:
int foo(int** arrayPtr) {
int* array = new int[10];
*arrayPtr = array;
return 0;
}
So, in the main I call the function that way:
int* myArray;
int ret;
ret = foo(&myArray);
Now myArray points to the new created array.
QUESTION 1: Is there a better way to do this?
Than the more interesting question.
If I pass NULL as parameter for foo, I generate an Access Violation exception because
*arrayPtr = array;
will try to write in 0x00000.
So, I added a try-catch block
int foo(int** arrayPtr) {
int* array = new int[10];
try {
*arrayPtr = array;
} catch(...) {
return 1;
}
return 0;
}
I expect that , when I call foo with NULL as parameter, it will return 1. Not true! It generate an exception.
QUESTION 2: Why the try-catch block in the DLL doesn't work?
Thanks to everyone!
P.S.: using try-catch for generating the same exception directly in the main doesn't generate an exception (or better, it's correctly handled by the try-catch block).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
假设您使用 VC++,
try..catch
默认情况下不会捕获访问冲突,因为默认异常处理模型仅捕获同步异常,而访问冲突是异步的 例外。这在此处记录:/EH(异常处理模型)如果您更改您的项目设置使用
/EHa
而不是/EHsc
那么您的try..catch
将捕获访问冲突。也就是说,为什么不显式检查
NULL
呢?使用异常进行流量控制是不好的形式。Assuming you're using VC++,
try..catch
will not catch access violations by default because the default exception handling model only catches synchronous exceptions and access violations are asynchronous exceptions. This is documented here: /EH (Exception Handling Model)If you change your project settings to use
/EHa
instead of/EHsc
then yourtry..catch
will catch the access violation.That said, why not explicitly check for
NULL
? Using exceptions for flow control is bad form.这几乎就是做到这一点的方法。只需确保公开一个函数来删除通过调用“foo”分配的内存块(以防万一您的 dll 使用与主应用程序不同的 CRT)。
访问冲突不应该抛出 C++ 异常,尽管 VC++ 中有一些设置可以将 SEH 异常映射到 C++ 异常,这通常被认为是一个坏主意。
That's pretty much the way to do it. Just be sure to expose a function to delete the memory block allocated by calls to "foo" (just in case your dll uses a different CRT than the main app).
Access violations are not supposed to throw C++ exceptions, although there is some setting in VC++ that would make a SEH exception to be mapped to a C++ one, which is generally considered a bad idea.
对于问题 1:
我看不出该功能有什么不好。你能用更好的方式定义你的意思吗?
您可以将 std::shared_ptr 与数组类型或 boost::shared_array 一起使用以获得更好的资源处理。但这取决于您要使用的界面。
对于问题 2:
当 arrayPtr 为 NULL 时,这将导致访问冲突。您无法使用 C++ try/catch 块捕获这些内容。
To question 1:
I don't see what is bad with the function. Can you define what you mean with better.
You could use std::shared_ptr with an array type or boost::shared_array to have a better resource handling. But this depends on the interface you want to use.
To question 2:
When arrayPtr is NULL this will create an access violation. You cannot catch those with c++ try/catch blocks.
2a.将 NULL 传递给函数似乎更像是调用方的错误。由于访问冲突而终止程序并非不合理。这将向调用者显示他的错误在哪里!
2b. catch 子句只能捕获从 C++ 代码引发的异常。硬件陷阱(如访问冲突)不会被捕获。
如果您不想
new
抛出任何一个,您可以使用new(std::nothrot) int[10];
2a. Passing NULL to your function seems more like an error on the calling side. Terminating the program with access violation in not unreasonable. That will show the caller where his error is!
2b. A catch clause can only catch exceptions that are thrown from the C++ code. Hardware traps, like an access violation, are not caught.
If you don't want
new
to throw either, you can usenew(std::nothrow) int[10];
有些系统根本不允许您捕获空引用异常,因此依赖于它们的处理是一个坏主意。特别是在您可以简单地进行检查的情况下。您的
foo
函数应如下所示:更好的方法是通过引用传递指针。这样,就无法传入 NULL 指针,并且您的问题将有效消失。
然后你的调用代码变成:
我认为还值得指出的是,对于你的原始代码,即使它按照你的预期工作,你的 catch 块也会泄漏分配的数组,因为你没有清理它:
Some systems won't let you catch null reference exceptions at all, so relying on handling for them is a bad idea. Particularly in a situation where you can simply do a check. Your
foo
function should look something like this:A better approach would be to pass the pointer in by reference. That way there's no way that a
NULL
pointer pointer can be passed in and your problem effectively goes away.Your calling code then becomes:
I think it's also worth pointing out that with your original code, even if it had worked as you expected your catch block would have been leaking the allocated array, since you weren't cleaning it up: