MFC defines functions to throw predefined exceptions. For example, you use ::AfxThrowFileException() to throw an exception of type CFileException. But what if I define my own exception class, which derives from CException? What is the preferred way to throw it?
Are there problems if I simply do this:
if (!m_Settings.IsValid())
throw new CMyException(_T("This operation failed."));
In Visual Studio 2019, the code above generates the following Intellisense warning. But I've yet to see any examples throwing an exception using make_unique.
Warning C26409 Avoid calling new and delete explicitly, use std::make_unique instead (r.11).
Can anyone explain this, or refer me to some current documentation?
Exception handling is one of those areas where it shows, that MFC predates C++ by a fair amount. With C++ exceptions being a late addition to the C++ Standard, MFC had already decided on its exception handling strategy:
Allocate exception objects on the freestore.
Throw by pointer.
Catch by pointer.
Any catch clause that handles an exception is required to release resources associated with the exception object.
By contrast, the idiomatic way to handle C++ exceptions follows these guidelines:
Throw exception objects with automatic storage duration by value.
Catch by (const) reference.
Cleanup of resources is handled automatically.
With MFC you can use either of the above. MFC provides exception macros to help make the former less error prone, although there is no strict requirement to use any of them. In fact, the exception macros in version 3.0 have moved on to almost exclusively use C++ exception handling under the hood.
The correct way to throw custom exceptions in MFC depends on the code that calls it. If that code is using the MFC exception macros, you will need to throw a pointer to the dynamically allocated exception object, e.g.
throw new CMyException(_T("This operation failed."));
or
THROW( (CException*) new CMyException(_T("This operation failed.")) );
and ignore the compiler warning. This is required because the CATCH macros will always expand to catch clauses matching pointer types.
If, on the other hand, calling code uses C++ exception handling, there's no issue throwing either by value or pointer, e.g.
throw CMyException(_T("This operation failed."));
// or
throw new CMyException(_T("This operation failed."));
and catching by const reference or pointer:
catch( CException const& ) {
// no cleanup required
}
// or
catch( CException* e ) {
// manual cleanup still required, unless the exception is re-thrown
e->Delete();
}
In the previous snippet it is also allowed to use both catch clauses, allowing you to provision your calling code to deal with a mixture of throwing custom exceptions by value in your code as well as calling into MFC-provided code that raises dynamically allocated exception objects thrown by pointer.
It is even allowed, to some extent, to mix C++ exception handling and MFC exception macros (Exceptions: Using MFC Macros and C++ Exceptions). The information is provided for completeness only. It is not recommended to mix C++ exceptions and MFC exception macros, unless there is a good reason to do so, e.g. when gradually transitioning existing code from MFC exception macro use to C++ exception handling.
Related
The pthread_mutex_init() function returns a non-zero value when it fails to initialize the mutex, while the std::mutex class in C++11 has a constructor of noexcept.
Say one chooses to implement a C++ mutex class on top of pthreads mutex. He wraps a pthread mutex inside the class and tries to initialize it by calling pthread_mutex_init() in constructor. If the function call returns a value other than zero, meaning error, the error can't be reported immediately since the constructor can not throw. One alternative is to throw an exception until the lock method is actually called on the mutex. But this approach just seems wrong.
Is there another way to do this, employing some clever tricks to guarantee that initializing a mutex always succeed?
Update: I am going to answer my own question on this one. According to language standard, in 30.4.1.3 pge 1163, it says ". If initialization of an object of a mutex type fails, an exception of type system_error shall be thrown. "
And a function of noexcept can throw inside the function body, it is just the caller can not catch the exception. If an exception is thrown inside a noexcept function, std::terminate will be called.
The constructor of std::mutex needs to be constexpr (so that a global std::mutex can be statically initialized and used in constructors of other global objects), and therefore cannot call pthread_mutex_init (or similar functions) at all.
Instead, it needs to use PTHREAD_MUTEX_INITIALIZER or equivalent (e.g., SRWLOCK_INIT on Windows) to statically initialize the mutex.
It seems to me that errors from pthread_mutex_init are simply ignored in libstdc++:
https://github.com/psp2sdk/libs/blob/master/include/c%2B%2B/bits/gthr-posix.h#L732
where __gthread_mutex_init_function is via macro __GTHREAD_MUTEX_INIT_FUNCTION invoked here
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/std_mutex.h#L75
that is in std::mutex constructor via its base class.
UPDATE
One can initialize Pthread mutex with PTHREAD_MUTEX_INITIALIZER and then
no error checks are performed
I guess error handling can be postponed to locking functions; quoting from documentation of pthread_mutex_lock and pthread_mutex_trylock ERRORS section:
EINVAL The value specified by mutex does not refer to an initialized mutex object.
This implies that errors in pthread_mutex_init can be safely ignored in std::mutex constructor.
According to C++17 specification:
33.4.3.2 Mutex types [thread.mutex.requirements.mutex]
The mutex types shall be DefaultConstructible and Destructible. If initialization of an object of a mutex type fails, an exception of type system_error shall be thrown. The mutex types shall not be copyable or movable.
So mutex type may throw an exception not std::mutex. std::mutex has noexcept, but std::recursive_mutex does not and they are both mutex types:
33.4.3.2.1 Class mutex [thread.mutex.class]
constexpr mutex() noexcept;
33.4.3.2.2 Class recursive_mutex [thread.mutex.recursive]
recursive_mutex();
Moreover:
20.5.5.12 Restrictions on exception handling [res.on.exception.handling]
Any of the functions defined in the C++ standard library can report a failure by throwing an exception of a type described in its Throws: paragraph, or of a type derived from a type named in the Throws: paragraph that would be caught by an exception handler for the base type.
Functions defined in the C++ standard library that do not have a Throws: paragraph but do have a potentially throwing exception specification may throw implementation-defined exceptions. Implementations should report errors by throwing exceptions of or derived from the standard exception classes (21.6.3.1, 21.8, 22.2).
There is no Throws paragraph and it does not have potentially throwing exception specification.
So std::mutex constructor shall never throw an exception or call std::terminate the same way as any other function from standard library with noexcept specification on conforming C++ implementation.
If you sum it all up this leads to the fact that pthread_mutex_init cannot be called in the std::mutex constructor. There does not need to be a one to one mapping for the construction/initialization. On the contrary!
I'm reading some libraries for my project.
Most of them specify "noexcept" in any move constructor.
Is it necessary to write "noexcept" in move constructors or is it occasionally just happened in my reading codes?
Thank you.
I think this explains the reason why you see noexcept in move constructors:
"A class provides the Strong Exception Guarantee if after an exception occurs, the objects maintain their original values. The move members of a class explicitly change the state of their argument. Should an exception be thrown after some members have been moved, then the Strong Exception Guarantee may no longer hold as the from object has been modified. It is especially important to use noexcept for types that are intended to be used with the standard library containers. If the move constructor for an element type in a container is not noexcept then the container will use the copy constructor rather than the move constructor."
So to answer your question, you should use noexcept in every case where your constructor could throw an exception. If you don't use one and if an exception occurs, the Strong Exception Guarantee will fail which could cause problems in the error recovery of your code.
Source: http://www.codingstandard.com/rule/12-5-4-declare-noexcept-the-move-constructor-and-move-assignment-operator/
I have this small method that helps me establish, if log4net is defined:
private static bool IsLog4netDefined()
{
return ExceptionHelper.Ignore(() => Assembly.Load("log4net,...")) != null;
}
While debugging unit tests, which don't use log4net, this method causes debugger to break on the exception being thrown, which drives me crazy. The exception is of course expected and is ignored.
I don't want to disable this particular exception in Debug -> Exceptions, as it is pretty generic (FileNotFoundException). I don't want to change any global VS settings.
Is there a way (something like pre-processor directive) to disable VS breaking in this method?
How about this?
DebuggerStepThrough attribute on the method that contains the code that you don't want to break on
DebuggerStepThrough attribute solution
Problem:
I have some code that is failing because an object has not been initialized. The solution for this bug is easy to fix, when detected. However, what surprised me is that my elaborate exception handling didn't catch this exception. That meant the exception wasn't logged or handled, and code following the try catch block was never executed. The try...catch block was outside of the transaction, so there was no issue there.
In this particular case, the exception was inside a batch (RunBaseBatch) job. The job handled several unrelated processing tasks. Once the exception conditions were met, the job terminated, so the other unrelated processing tasks were never called.
Does anyone know if it is possible to catch an "object not initialized" exception in Dynamics AX 2009? I read one post that said it may not be possible to catch certain exceptions in AX, however, I hope that is not the case (reference: https://community.dynamics.com/product/ax/f/33/p/16352/23700.aspx#23700).
Code example:
Here is some simplistic code that recreates the issue:
server static void main(Args args)
{
Array arr;
;
info ("debug: before try...catch");
try
{
// ttsbegin; // enable/disable to test with transactions
// arr = new Array(Types::String); // Enabling this line will prevent the exception
arr.exists(3);
// ttscommit; // enable/disable to test with transactions
}
catch (Exception::Internal) // This exception handler was the Magic Sauce!!
{
info ("debug: catch (Exception::Internal)");
}
catch (Exception::Error)
{
info ("debug: catch (Exception::Error)");
}
catch
{
info ("debug: catch");
}
info ("debug: after try...catch");
}
UPDATE 2013-01-29
I am waiting to accept an answer until this question has been viewed more. Thank you for the answers so far.
I know the example I gave was simplistic. This type of bug is easily fixable when it is known. And defensive programming is always a good idea.
However, in the real world, the code where the bug occurred was very complex. The error occurred several levels deep in an overloaded method of a subclass. It occurred in a specific scenario, when an overloaded method corrupted the protected value of a member variable from the super class. That is where the bug occurred in the code, however, it didn't manifest itself until the super class tried to use the member variable again. The bug was summarily fixed when it was detected and tracked down.
Defensively, yes you could check every protected member variable, every time you use it, but that does start to impact performance, code readability, practicality, etc., which is why languages offer exception handling.
The question here, is how can these type of bugs be caught to make code more robust and bullet-proof? In most development environments (C, C++, C#, or Java for example), a try...catch at a top level could be used to catch, log, and clean up ALL unexpected exceptions. So the code would be able to continue processing with the other unrelated tasks. AX is continuing at some level, because the whole system doesn't come to a grinding halt when this bug occurs. However, the code after the catch in this job is not executing because of what appears to be a deficiency in AX/X++.
I am looking for an innovative solution or work-around, if it exists, to catch the "object not initialized" exception (really ALL exceptions) and to continue processing.
You cannot "catch" it in the traditional sense, but you can avoid it happening. Simply test if the object exists before running anything from it:
if(object)
{
// Exists; Execute statements with object here
}
else
{
// Doesn't exist
}
This works because object will be translated as null if it is not initialized.
(Null == 0) == false
If the object is initialized it will have some value other than null.
(!Null != 0) == true
Hope that helps!
You can, but you shouldn't. A behavior like this is almost certainly a bad design of your code, that will inevitably end in more problems in the future.
You need to make your code defensive to this case, making sure the object is instanciated before using it. Otherwise, you're using the catch code to an expected behavior, wich makes no sense.
EDIT 2013/02/18
In complex scenarios like what you're describing, it's usually very hard to get a solution fully controlled. In AX, try..catch statement is quite simplified and in a very large range of situations is not really needed (unlike Java, C#, ... where is always recommended).
This simplification is nice in almost all situations of AX development, as you don't need to waste time on exception handling. Just let them raise, and the InfoLog will handle them on a simple and reliable way.
The big problem comes where you really need this control... when there is not really a way of force it. I'm not sure if this is really an standard issue or it's espected by the product team to work that way, but this cases are always giving troubles in AX. When you need to catch some specific issue you have to be very creative and deffensive to prevent the exception as catching it will become even more creative...
Hope this helps :)
To elaborate a little, as stated in the post you linked to you cannot catch an Object Not Initialized error. However, you can "fix" the code by adding a simple check before attempting to run functions against a variable that you do not control (for example, if you are requesting an Array type as an argument for a function and you expect the function to be called from outside the class).
try
{
if (arr)
arr.exists(3);
}
The if(arr) statement is enough to skip the processing if the object has not yet been instantiated, effectively bypassing the error. However, this will obviously not throw the error further up the chain. If you really wanted, you could make it throw a different error that can be caught, but obviously that is less than ideal.
In this case, since the RunBaseBatch class may not be something you want to modify it would probably be better to make sure the object that is causing the issue is correctly defined before calling the problem method, and finding these errors in testing.
Visual Studio Test can check for expected exceptions using the ExpectedException attribute. You can pass in an exception like this:
[TestMethod]
[ExpectedException(typeof(CriticalException))]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
You can also check for the message contained within the ExpectedException like this:
[TestMethod]
[ExpectedException(typeof(CriticalException), "An error occured")]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
But when testing I18N applications I would use a resource file to get that error message (any may even decide to test the different localizations of the error message if I want to, but Visual Studio will not let me do this:
[TestMethod]
[ExpectedException(typeof(CriticalException), MyRes.MultipleOrganisationsNotAllowed)]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
The compiler will give the following error:
An attribute argument must be a
constant expression, typeof expression
or array creation expression of an
attribute
Does anybody know how to test for an exception that has a message from a resource file?
One option I have considered is using custom exception classes, but based on often heard advice such as:
"Do create and throw custom exceptions
if you have an error condition that
can be programmatically handled in a
different way than any other existing
exception. Otherwise, throw one of the
existing exceptions." Source
I'm not expecting to handle the exceptions differently in normal flow (it's a critical exception, so I'm going into panic mode anyway) and I don't think creating an exception for each test case is the right thing to do. Any opinions?
I would recommend using a helper method instead of an attribute. Something like this:
public static class ExceptionAssert
{
public static T Throws<T>(Action action) where T : Exception
{
try
{
action();
}
catch (T ex)
{
return ex;
}
Assert.Fail("Exception of type {0} should be thrown.", typeof(T));
// The compiler doesn't know that Assert.Fail
// will always throw an exception
return null;
}
}
Then you can write your test something like this:
[TestMethod]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
{
OrganizationList organizations = new Organizations();
organizations.Add(new Organization());
organizations.Add(new Organization());
var ex = ExceptionAssert.Throws<CriticalException>(
() => organizations.GetOrganization());
Assert.AreEqual(MyRes.MultipleOrganisationsNotAllowed, ex.Message);
}
This also has the benefit that it verifies that the exception is thrown on the line you were expecting it to be thrown instead of anywhere in your test method.
The ExpectedException Message argument does not match against the message of the exception. Rather this is the message that is printed in the test results if the expected exception did not in fact occur.
Just an opinion, but I would say the error text:
is part of the test, in which case getting it from the resource would be 'wrong' (otherwise you could end up with a consistantly mangled resource), so just update the test when you change the resource (or the test fails)
is not part of the test, and you should only care that it throws the exception.
Note that the first option should let you test multiple languages, given the ability to run with a locale.
As for multiple exceptions, I'm from C++ land, where creating loads and loads of exceptions (to the point of one per 'throw' statement!) in big heirachies is acceptable (if not common), but .Net's metadata system probably doesn't like that, hence that advice.
I think you can just do an explicit try-catch in your test code instead of relying on the ExpectedException attribute to do it for you. Then you can come up with some helper method that will read the resource file and compare the error message to the one that comes with the exception that was caught. (of course if there wasn't an exception then the test case should be considered a fail)
If you switch over to using the very nice xUnit.Net testing library, you can replace [ExpectedException] with something like this:
[Fact]
public void TestException()
{
Exception ex = Record.Exception(() => myClass.DoSomethingExceptional());
// Assert whatever you like about the exception here.
}
I wonder if NUnit is moving down the path away from simplicity... but here you go.
New enhancements (2.4.3 and up?) to the ExpectedException attribute allow you more control on the checks to be performed on the expected Exception via a Handler method. More Details on the official NUnit doc page.. towards the end of the page.
[ExpectedException( Handler="HandlerMethod" )]
public void TestMethod()
{
...
}
public void HandlerMethod( System.Exception ex )
{
...
}
Note: Something doesn't feel right here.. Why are your exceptions messages internationalized.. Are you using exceptions for things that need to be handled or notified to the user. Unless you have a bunch of culturally diverse developers fixing bugs.. you shouldn't be needing this. Exceptions in English or a common accepted language would suffice. But in case you have to have this.. its possible :)
I came across this question while trying to resolve a similar issue on my own. (I'll detail the solution that I settled on below.)
I have to agree with Gishu's comments about internationalizing the exception messages being a code smell.
I had done this initially in my own project so that I could have consistency between the error messages throw by my application and in my unit tests. ie, to only have to define my exception messages in one place and at the time, the Resource file seemed like a sensible place to do this since I was already using it for various labels and strings (and since it made sense to add a reference to it in my test code to verify that those same labels showed in the appropriate places).
At one point I had considered (and tested) using try/catch blocks to avoid the requirement of a constant by the ExpectedException attribute, but this seemed like it would lead to quite a lot of extra code if applied on a large scale.
In the end, the solution that I settled on was to create a static class in my Resource library and store my exception messages in that. This way there's no need to internationalize them (which I'll agree doesn't make sense) and they're made accessible anytime that a resource string would be accessible since they're in the same namespace. (This fits with my desire not to make verifying the exception text a complex process.)
My test code then simply boils down to (pardon the mangling...):
[Test,
ExpectedException(typeof(System.ArgumentException),
ExpectedException=ProductExceptionMessages.DuplicateProductName)]
public void TestCreateDuplicateProduct()
{
_repository.CreateProduct("TestCreateDuplicateProduct");
_repository.CreateProduct("TestCreateDuplicateProduct");
}