some problems about c++ try catch [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a question about try catch mechanism. like code:
global value default 0;
int thread1()
{
try
{
set global value to 1;
if exception happens
{
jump into catch;
}
set global value to 0;
}
catch
{
......
}
}
int thread2()
{
ASSERT(global value = 0);
}
If I have the fake code as shown, in try block I set a global value to 1 and then an exception happens, in thread2 I have a ASSERT to test if this global value is equal to 0, then thread2 will failed explicitly because in thread1, we jump into the catch block because of an exception. So can anybody give me some explanation ? I don't know how try--catch works to prevent this.

Exceptions are brutal break of the normal flow of execution. The error correcting flow is to find a catch that correspond to the object thrown; this may lead to several function calls reverse traversal. This is why it needs care to use them, you have two flow of execution : the normal one, and the error one.
If the exception thrown is catched by the catch-block directly after, then you just have to set your variable to 0 in the catch-block.
It not, a good solution is RAII (as suggested in comments). RAII is a very simple idea. As you know that every object created on stack at the entry of any block is destroyed when control leave the block, the idea is to build an object that encapsulate something, so that the destructor will be called whatever happens:
class GlobalControl {
public:
GlobalControl() { myglob = 1; } // RAII
~GlobalControl() { myglob = 0; } // RRID
};
... // somewhere else
try {
GlobalControl c; // ctor call init glob to 1
...
} // whatever will happens, leaving this block cause a call to dtor of c
catch (...) {
}
RAII stands for Resource Acquisition Is Initialization, here your resource acquisition is to set your global to 1, and this is made in the initialization part of the object. RAII should be called RAIIRRID, RAII + Resource Releasing Is Destruction (the resource release is to set your global to 0, and this is made in the destructor).

Related

SDL Multithreading with variables -- Doesn't work as expected [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have in a namespace called Main an static integer, and a static class variable called other, like this:
namespace Main {
void test();
static Client other;
static int v = 0;
}
Then, when the program starts, Main::test() is called, and creates a thread via SDL:
void test() {
SDL_CreateThread(Client::test, (const char*)"Client", (void*)NULL);
v = 1;
std::cout << v << std::endl;
...
}
This makes the Client start a function called test, which prints the vector size forever, like so:
int Client::test(void* data)
{
while(1) {std::cout << Main::v << std::endl; }
}
Now, here's the problem! Main returns 1 and Client returns a lot of zeros! What happened there? The variable is static, so it should be the same for Client!
std::vector.size() is, by definition, the number of elements in the vector.
Any situation where you think that isn't the case, or you see symptoms of that not being the case, you are probably experiencing undefined behavior due to memory corruption or out-of-bounds accesses.
Note that assigning to an indexed location of a vector v[n] = x; does not extend the vector, and is undefined behavior if n >= v.size().
Without explicit synchronization, the compiler is allowed to optimize the Client::test method by assuming that v never changes.
This is because it obviously doesn't change in that thread, it's your responsibility to tell the compiler if it could change in a different thread, and you did no such thing.
You are using a standard container in two threads, so you need to protect every access with a mutex. That creates a memory fence (which solves the problem you've seen), and protects from internal corruption when you perform actions on the container from different threads simultaneously (which your answer does not attempt to solve).

Proper error handling in destructors

This is kind of concept question.
Lets assume that we have some code base that works with hardware from high level and whole error handling mechanism is implemented by exceptions. Lets assume that we are opening/closing some valve(s). As long this hardware operation have finalizing procedure we need to use RAII conception. So some foo() procedure could look like this:
class Valve()
{
public:
Valve()
{
// open valve
}
~Valve()
{
// close valve
// Potential exception here
}
private:
// valve internal stuff
}
void foo()
{
try
{
Valve v;
bar1(v); // <--- throws something
} catch(...)
{
// report error and exit
// it's guaranteed that valve destructor will be called
}
}
This piece of code looks nice, but how we can manage errors that could happen during valve closing. Exception couldn't leave destructor. The only way I see is keeping error in some error storage, like this:
Valve::~Valve()
{
try
{
// close valve
} catch(...)
{
errorStorage.Add(...);
}
}
But this approach looks ugly. Are there any ideas how to deal in this situation? Of course one way is not using of the exceptions at all, but use return code approach and some cleanup action (with goto in case of error).
UP:
Originally I wanted to avoid this kind of logic duplication:
void foo()
{
try
{
Valve v;
v.open(); // <- could throw
bar1(v); // <- could throw
v.close(); // <- could throw
} catch(...)
{
if(v.opened())
v.close(); // kind of logic duplication
}
}
Another approach would be for the destructor to handle the error directly.
Valve::~Valve()
{
try
{
// close valve
} catch(...)
{
// handle valve close error
}
}
Admittedly, someone could probably come up with a case when this is inadequate, but the question lacks the details for that sort of determination. (Lacking those details may be a good thing, if the intent is to find a variety of answers. After all, it is self-described as a "concept question".) Simple logging of which valve failed to close is one case where this should work.
At a high level, I would expect this approach to simplify the code overall, since the handling of the valve close error has been localized to the Valve class. Code using the Valve class would not need to know that a valve can be closed, much less that an error could occur while closing a valve, which improves data encapsulation.
Naturally, this approach does require that no exceptions are thrown by the code that handles the valve close error. (This is probably a good goal anyway, since it is part of error handling.)
The plan to add the error to some sort of error storage looks dubious to me. I see "add" and I think "possibly allocates memory", which implies "possibly throws an exception if memory has been exhausted". So I'd wonder if steps had been taken to prevent an exception being thrown by this mechanism that is supposed to delay the throwing of an exception. Does this solve the problem or just make it less likely?

Good or bad: Calling destructor in constructor [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Break: I don't think it is the same question actually, the other question is a general question about calling destructors manually. This is at the creating process, inside the class itself. Still want to know what happen when you do this, like stated in the question below.
At first, I think it is bad, real bad. Just analysing this piece of code of a constructor (see below), made by two guys and need it to translate it to Delphi object Pascal. It must behave the same like the C-version. I don't like the style, very ugly but never mind.
Another thing, at two stages in the code it calls the destructor when fail (I suppose to close the connection however the destructor is automaticly called when deleted, why want you do this anyway?). I think that is not the way to do it or do miss something inhere?
Also, after calling the destructor, they want to throw an exception (huh?) however I think this will never be executed and cause another exeption when you manually want to access it or want to delete it.
Serial::Serial(
std::string &commPortName,
int bitRate,
bool testOnStartup,
bool cycleDtrOnStartup
) {
std::wstring com_name_ws = s2ws(commPortName);
commHandle =
CreateFileW(
com_name_ws.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if(commHandle == INVALID_HANDLE_VALUE)
throw("ERROR: Could not open com port");
else {
// set timeouts
COMMTIMEOUTS timeouts;
/* Blocking:
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
Non-blocking:
timeouts = { MAXDWORD, 0, 0, 0, 0}; */
// Non-blocking with short timeouts
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutMultiplier = 1;
timeouts.ReadTotalTimeoutConstant = 1;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 1;
DCB dcb;
if(!SetCommTimeouts(commHandle, &timeouts)) {
Serial::~Serial(); <- Calls destructor!
throw("ERROR: Could not set com port time-outs");
}
// set DCB; disabling harware flow control; setting 1N8 mode
memset(&dcb, 0, sizeof(dcb));
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = bitRate;
dcb.fBinary = 1;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 8;
if(!SetCommState(commHandle, &dcb)) {
Serial::~Serial(); <- Calls destructor!
throw("ERROR: Could not set com port parameters");
}
}
if(cycleDtrOnStartup) {
if(!EscapeCommFunction(commHandle, CLRDTR))
throw("ERROR: clearing DTR");
Sleep(200);
if(!EscapeCommFunction(commHandle, SETDTR))
throw("ERROR: setting DTR");
}
if(testOnStartup) {
DWORD numWritten;
char init[] = "PJON-python init";
if(!WriteFile(commHandle, init, sizeof(init), &numWritten, NULL))
throw("writing initial data to port failed");
if(numWritten != sizeof(init))
throw("ERROR: not all test data written to port");
}
};
Serial::~Serial() {
CloseHandle(commHandle);
};
// and there is more etc .......
// .............
Next question, what will actually happen in memory when executing this code and it calls the destructor? I am not able to execute it and debug it.
This code is ugly but legal. When an exception is thrown from constructor, the corresponding destructor is never called. So calling it manually before throwing is needed to prevent the resource leak. The real bug here is not calling destructor manually in other cases before throwing exception.
Of course, a better way of doing this is having a separate RAII object that encapsulates commHandle. A unique_ptr with custom deleter can serve this role.
Any destructor beyond low-level libraries is a code smell in modern C++.
Well, let's start by saying the obvious: don't write code this way. I can see why they did it - calling the destructor manually was a convenient way to clean up before throwing that exception, but why is it such a bad idea?
Well, the destructor is normally only called if the constructor runs to completion (so it won't be run, in the normal way of things, if the constructor throws) and this is deliberate as it allows the destructor to assume that the object has been fully initialised. A destructor of any complexity that tries to tear down an object which is not fully initialised is likely to run into trouble.
Now none of this matters in the code as written, because all we have here is a tinpot destructor that just closes the handle so, here, the code does correctly clean up before throwing (sometimes, thank you Eugene) and we can all sit down and relax. But as a programming pattern it stinks, and, now that you know what it actually does you should tidy it up when you move it to Delphi.
So, lecture over, a few specifics (in no particular order):
When you call a destructor manually, it's just like calling any other function - it is executed and it returns and life goes on. Specifically, the object itself is not deallocated. Doing this has value when using placement new.
It follows from the above that that call to throw will be executed after the destructor returns (it would be anyway, regardless).
Just to repeat, when a constructor throws, the destructor is not called. The object will be deallocated subsequently however, before the exception is caught (if it ever is), I believe.
If the rest of the code you have to convert is written in such a slapdash manner, I don't envy you. Constructors shouldn't fail anyway, in the general run of things, just open the port in a separate method once the object is up and running.
When you throw from the constructor, it will call the destructor of any object constructed so far: the member variables and the inherited classes (section 15.2/2).
An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects
If you call the destructor manually, their destructor will be also called (section 12.4/8).
After executing the body of the destructor and destroying any automatic objects allocated within the body, a
destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors
for X’s direct base classes ...
Therefore the destructor of member variables will be called twice. Formally, calling twice a destructor is undefined behavior. (You may get away with it if they all had empty destructor.)
If you really need a clean solution, wrap the parts that need to be cleaned into a class and make it a member variable. Call the initialisation from it and if you throw, you are guaranteed that it will be cleaned.
You even get kudo points for applying RAII.

If a constructor throws exception, then does it make sense to have a global object of that class?

I am asking this question for general coding guidelines:
class A {
A() { ... throw 0; }
};
A obj; // <---global
int main()
{
}
If obj throws exception in above code then, it will eventually terminate the code before main() gets called. So my question is, what guideline I should take for such scenario ? Is it ok to declare global objects for such classes or not ? Should I always refrain myself from doing so, or is it a good tendency to catch the error in the beginning itself ?
If you NEED a global instance of an object whose constructor can throw, you could make the variable static, instead:
A * f(){
try {
//lock(mutex); -> as Praetorian points out
static A a;
//unlock(mutex);
return &a;
}
catch (...){
return NULL;
}
}
int main() {
A * a = f(); //f() can be called whenever you need to access the global
}
This would alleviate the problem caused by a premature exception.
EDIT: Of course, in this case the solution is 90% of the way to being a Singleton. Why not just fully turn it into one, by moving f() into A?
No, you should not declare such objects global - any exception will be unhandled and very hard to diagnose. The program will just crash which means that it will have very poor (below zero) user experience and will be rather hard to maintain.
As #Kerrek SB has mentioned in the comments, the answer to this is dependent on the reasons that can cause your class to throw. If you're trying to acquire a system resource that might be unavailable, I feel you shouldn't declare a global object. Your program will crash as soon as the user tries to run it; needless to say, that doesn't look very good. If it can throw a std::bad_alloc or some such exception that is unlikely under normal circumstances (assuming you're not trying to allocate a few GB of memory) you could make a global instance; however, I would still not do that.
Instead, you could declare a global pointer to the object, instantiate the object right at the beginning of main (before any threads have been spawned etc.) and point the pointer to this instance, then access it through the pointer. This gives your program a chance to handle exceptions, and maybe prompt the user to take some sort of remedial measures (like popping up a Retry button to try and reacquire the resource, for instance).
Declaring a global object is fine, but the design of your class is insignificant, it lacks details to be compatible with practical needs and use.
One solution no one seems to have mentionned is to use a function try
block. Basically, if the situation is that without the constructed
object, the rest of your program won't work or be able to do anything
useful, then the only real problem is that your user will get some sort
of incomprehensible error message if the constructor terminates with an
exception. So you wrap the constructor in a function try block, and
generate a comprehensible message, followed by an error return:
A::() try
: var1( initVar1 )
// ...
{
// Additional initialization code...
} catch ( std::exception const& ) {
std::cerr << "..." << std::endl;
exit(EXIT_FAILURE);
} catch (...) {
std::cerr << "Unknown error initializing A" << std::endl;
exit(EXIT_FAILURE);
}
This solution is really only appropriate, however, if all instances of
the object are declared statically, or if you can isolate a single
constructor for the static instances; for the non-static instances, it
is probably better to propagate the exception.
Like #J T have said, you can write like this:
struct S {
S() noexcept(false);
};
S &globalS() {
try {
static S s;
return s;
} catch (...) {
// Handle error, perhaps by logging it and gracefully terminating the application.
}
// Unreachable.
}
Such scenario is quite a problem, please read ERR58-CPP. Handle all exceptions thrown before main() begins executing for more detail.

Way for C++ destructor to skip work when specific exception being thrown?

I have an object on the stack for which I wish its destructor to skip some work when the destructor is being called because the stack is being unwound due to a specific exception being thrown through the scope of the object on the stack.
Now I could add a try catch block inside the scope of the stack item and catch the exception in question and notify the stack object to not run the work to be skipped an then rethrow the exception as follows:
RAII_Class pending;
try {
doSomeWorkThatMayThrowException();
} catch (exceptionToSkipPendingDtor &err) {
pending.notifySkipResourceRelease();
throw;
}
However, I'm hoping there is a more elegant way to do this. For example imagine:
RAII_Class::~RAII_Class {
if (detectExceptionToSkipPendingDtorBeingThrown()) {
return;
}
releaseResource();
}
You can almost do this with std::uncaught_exception(), but not quite.
Herb Sutter explains the "almost" better than I do: http://www.gotw.ca/gotw/047.htm
There are corner cases where std::uncaught_exception() returns true when called from a destructor but the object in question isn't actually being destroyed by the stack unwinding process.
You're probably better off without RAII because it doesn't match your use case. RAII means always clean up; exception or not.
What you want is much simpler: only release resource if an exception is not throw which is a simple sequence of functions.
explicitAllocateResource();
doSomeWorkThatMayThrowException();
explicitReleaseResource(); // skipped if an exception is thrown
// by the previous function.
I would do it the other way around - explicitly tell it to do its work if no exception was thrown:
RAII_Class pending;
doSomeWorkThatMayThrowException();
pending.commit(); // do or prepare actual work
This seems to circumvent the main reason to use RAII. The point of RAII is that if an exception happens in the middle of your code you can still release resources/be destructed properly.
If this isn;t the semantic you want, then don't use RAII.
So instead of:
void myFunction() {
WrapperClass wc(acquireResource());
// code that may throw
}
Just do:
void myFunction() {
Resource r = acquireResource();
// code that may throw
freeResource(r);
}
If the code in the middle throws, the resource won't be freed. This is what you want, rather than keeping RAII (and keeping the name) but not implementing RAII semantics.
Looks like bool std::uncaught_exception(); does the trick if you want to have this behavior for every exception, not just special ones!
You can do without a try-catch:
RAII_Class pending;
doSomeWorkThatMayThrowException(); // intentional: don't release if throw
pending.releaseResource();
Alternatively, you can try a little harder with RAII:
struct RAII_Class {
template<class Op>
void execute(Op op) {
op();
releaseResources();
}
private:
void releaseResources() { /* ... */ }
};
int main(int argc, char* argv[])
{
RAII_Class().execute(doSomeWorkThatMayThrowException);
return 0;
}
Although it would be a kludge at best, if you own the code for the exception class you're interested in, you could add a static data member to that class (bool) that would be set to "true" in the constructor for objects of that class, and false in the destructor (might need to be an int that you increment/decrement instead). Then in the destructor of your RAII class, you can check std::uncaught_exception(), and if true, query the static data member in your exception class. If you get true (or > 0) back, you've got one of those exceptions--otherwise you ignore it.
Not very elegant, but it would probably do the trick (as long as you don't have multiple threads).
I found this website with an interesting discussion about std::uncaught_exception() and an alternative solution to your question that seems much more elegant and correct to me:
http://www.gotw.ca/gotw/047.htm
// Alternative right solution
//
T::Close() {
// ... code that could throw ...
}
T::~T() /* throw() */ {
try {
Close();
} catch( ... ) {
}
}
In this way you're destructor does only one thing and you're protected against throwing an exception during an exception (which I assume is the problem you're trying to solve).