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).
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.
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.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.
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:
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];