我正在开发一个为主应用程序分配数组的C ++ DLL。 该函数返回错误代码而不是指向新创建的数组的指针,因此第一个成员的地址将写入函数的参数中。 例如:
int foo(int** arrayPtr) {
int* array = new int[10];
*arrayPtr = array;
return 0;
}
所以,在主要方面我用这种方式调用函数:
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块不起作用?
感谢大家!
P.S。:使用try-catch直接在main中生成相同的异常不会产生异常(或者更好,它由try-catch块正确处理)。
答案 0 :(得分:1)
假设您正在使用VC ++,try..catch
默认情况下不会捕获访问冲突,因为默认的异常处理模型仅捕获同步异常,并且访问冲突是异步< / em>例外。这在此处记录:/EH (Exception Handling Model)
如果您将项目设置更改为使用/EHa
而不是/EHsc
,那么您的try..catch
将会遇到访问冲突。
那说,为什么不明确检查NULL
?使用流控制的例外是错误形式。
int foo(int** arrayPtr) {
if (!arrayPtr)
return 1;
*arrayPtr = new int[10];
return 0;
}
答案 1 :(得分:1)
这几乎就是这样做的。只需确保公开一个函数来删除通过调用“foo”分配的内存块(以防你的dll使用与主应用程序不同的CRT)。
访问冲突不应该抛出C ++异常,尽管VC ++中有一些设置可以将SEH异常映射到C ++异常,这通常被认为是个坏主意。
< / LI> 醇>答案 2 :(得分:0)
问题1:
我没有看到这个功能有什么不好。你能更好地定义你的意思吗?
您可以将std :: shared_ptr与数组类型或boost :: shared_array一起使用以获得更好的资源处理。但这取决于您要使用的界面。
问题2:
try {
*arrayPtr = array;
} catch(...) {
return 1;
}
当arrayPtr为NULL时,这将创建访问冲突。你无法用c ++ try / catch块来捕获它们。
答案 3 :(得分:0)
有些系统根本不会让你捕获空引用异常,所以依赖于处理它们是一个坏主意。特别是在您可以简单地进行检查的情况下。您的foo
函数应如下所示:
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;
}
更好的方法是通过引用传递指针。这样就无法传入NULL
指针指针,你的问题就会有效消失。
// 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;
}
您的主叫代码将变为:
int* myArray;
int ret;
ret = foo(myArray); // Pass in by reference
我认为值得指出的是,使用原始代码,即使它按预期工作,你的catch块也会泄漏分配的数组,因为你没有清理它:
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;
}
答案 4 :(得分:0)
2a上。将NULL传递给您的函数似乎更像是调用端的错误。使用访问冲突终止程序并非不合理。这将向调用者显示他的错误!
2B。 catch子句只能捕获从C ++代码抛出的异常。硬件陷阱(如访问冲突)不会被捕获。
如果您不希望new
投掷任何一个,可以使用new(std::nothrow) int[10];