Prevent C++ DLL exception using try catch internally
我正在开发一个C++ DLL,它为主应用程序分配一个数组。函数返回错误代码,而不是指向新创建数组的指针,因此第一个成员的地址将写入函数的参数中。例子:
1 2 3 4 5 | int foo(int** arrayPtr) { int* array = new int[10]; *arrayPtr = array; return 0; } |
所以,我主要是这样调用函数:
1 2 3 | int* myArray; int ret; ret = foo(&myArray); |
现在,myarray指向新创建的数组。
问题1:有更好的方法吗?
而不是更有趣的问题。如果我将空值作为foo的参数传递,我会生成一个访问冲突异常,因为
1 | *arrayPtr = array; |
将尝试写入0x00000。
所以,我添加了一个try-catch块
1 2 3 4 5 6 7 8 9 | int foo(int** arrayPtr) { int* array = new int[10]; try { *arrayPtr = array; } catch(...) { return 1; } return 0; } |
我希望,当我使用空值作为参数调用foo时,它将返回1。不是真的!它生成一个异常。
问题2:为什么dll中的try catch块不起作用?
谢谢大家!
P.S.:使用try catch直接在main中生成相同的异常不会生成异常(或者更好的是,它由try catch块正确处理)。
这几乎就是做到这一点的方法。只需确保公开一个函数来删除调用"foo"分配的内存块(以防您的dll使用不同于主应用程序的crt)。
访问违反不应该抛出C++异常,尽管在VC++中有一些设置会使SEH异常映射到C++中,这通常被认为是一个坏主意。
假设您使用的是VC++,那么默认情况下,
如果您将项目设置更改为使用
这就是说,为什么不明确检查一下
1 2 3 4 5 6 | int foo(int** arrayPtr) { if (!arrayPtr) return 1; *arrayPtr = new int[10]; return 0; } |
将空值传递给函数更像是调用端的错误。以不合理的访问冲突终止程序。这将向来电者显示他的错误所在!
2B.catch子句只能捕获从C++代码中抛出的异常。硬件陷阱(如访问冲突)不会被捕获。
如果你不想让
有些系统根本不允许捕获空引用异常,因此依赖于对它们的处理是一个坏主意。尤其是在你可以简单地检查的情况下。您的
1 2 3 4 5 6 7 8 9 10 | int foo(int** arrayPtr) { // If a valid pointer has been passed in... if(arrayPtr) { // update the pointer to point at the allocated memory. *arrayPtr = new int[10]; return 0; } return 1; } |
更好的方法是通过引用传递指针。这样,就不可能传入
1 2 3 4 5 6 7 | // Pass in a reference to an array pointer. The reference can't be NULL... int foo(int* &arrayPtr) { // update the reference arrayPtr = new int[10]; return 0; } |
然后您的呼叫代码变为:
1 2 3 | int* myArray; int ret; ret = foo(myArray); // Pass in by reference |
我认为还值得指出的是,对于您的原始代码,即使它按预期工作,您的catch块也会泄漏分配的数组,因为您没有清除它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int foo(int** arrayPtr) { int* array = new int[10]; try { *arrayPtr = array; } catch(...) { // EVEN IF THIS HAD WORKED AS INTENDED, YOU LEAK array BECAUSE IT'S NOT DELETED // delete array; // is missing return 1; } return 0; } |
质疑1:我看不出这个功能有什么问题。你能用"更好"来定义你的意思吗?您可以将std::shared_ptr与数组类型一起使用,或者使用boost::shared_数组来更好地处理资源。但这取决于您想要使用的接口。
质疑2:
1 2 3 4 5 | try { *arrayPtr = array; } catch(...) { return 1; } |
当arraypter为空时,这将创建一个访问冲突。不能用C++尝试/ catch块来捕获这些。