I'm always reading that I should not to throw a std::string or some other classes allocating memory. like here or more importantly here on point 3. - Don't embed a std::string object.
So now I'm trying to insert boost::exception to my project and what do I see: lots of strings.
Why doesn't boost comply with its own recommendation?
And if I have parameters which can't be hardcoded, like safed in an config-file, how can I put them into an exception, without using std::string?
Or is the guideline don't use std::string only a do use std::string as seldom as possible guideline? I'm a bit confused...
I've done some research. Please correct me if i'm wrong.
If I understand it right, it's all about the allocation during the throw and what is happening to the allocated memory. So the memory gets lost if I allocate it in the constructor and it can't be freed in the destructor of the exception, that will produce a memory-leak. But it's okay to allocate this before throwing, so the exception is clean.
I tried this:
struct xexception {
int *ttt[10];
xexception() {
ttt[0] = new int[0xfffffffL];
ttt[1] = new int[0xfffffffL];
ttt[2] = new int[0xfffffffL];
ttt[3] = new int[0xfffffffL];
ttt[4] = new int[0xfffffffL];
ttt[5] = new int[0xfffffffL];
ttt[6] = new int[0xfffffffL];
ttt[7] = new int[0xfffffffL];
ttt[8] = new int[0xfffffffL];
ttt[9] = new int[0xfffffffL];
}
~xexception() throw() {
//never happen
delete[] ttt[0];
delete[] ttt[1];
delete[] ttt[2];
delete[] ttt[3];
delete[] ttt[4];
delete[] ttt[5];
delete[] ttt[6];
delete[] ttt[7];
delete[] ttt[8];
delete[] ttt[9];
}
};
int main(int argc, const char *argv[]) {
try {
throw(xexception());
}
catch (const xexception &e) {
std::cerr << "\nttt " << e.ttt[0][0] << std::endl;
}
catch (std::bad_alloc) {
std::cerr << "bad alloc" << std::endl;
}
return 0;
}
The result is, I get the bad_alloc and a huge memory leak.
Now if I do the allocation before, it also throws the bad_alloc but before the exception is created.
My exception to the exception concept is:
Who cares? If I have a bad_alloc in my program, because of a memory_leak or something else (I'm talking about programs on PCs not microcontrollers) I have other problems. Maybe I can figure out that a bad_alloc happened, but where? On my alloc during a function (one of maybe 1000) or in the std::string (well I know it's the string but ... no possibility to manipulate the memory of the string... or its to dissipated).
try {
// where is the error???
int *x = new int[100]; // here?
....
int *y = new int[100]; // or here?
....
int *z = new int[100];
....
int *w = new int[100];
....
int *t = new int[100];
....
int *f = new int[100];
....
std::string str("asdfasdfasdfasdfasdfasdfasdf"); // maybe here
}
catch (the error) {
....
}
And then? Shall I try to figure out where it's happening? Therefore I would use valgrind not exceptions.
void foo() {
int *i = new int[1];
foo();
}
try {
foo();
}
chatch( bad_boy ) {
go_exception_handler_go(parameters); // oh, shit happens: also an stack_overflow may happend, cause stack is also full
}
Or shall i manipulate the errormessage and log it, what definitively would throw the next bad_alloc.
Please don't misunderstand me. Since I've seen the boost::exception I've rewritten my exception class (till waiting on an answer) but I also think it is not really necessary to pick up every grain of sand.
The advice is basically telling you "Don't use any construct that might throw an exception in an exception". That's because if you get an exception while trying to throw an exception, the C++ runtime will just immediately call terminate() and kill your program.
Now if (either) of the exceptions involved would just call terminate() anyways (as is the default for an uncaught exception), then you don't really need to worry about it. For example, if your application can't handle bad_alloc (can't recover from out-of-memory), then you don't need to worry about copy constructors (such as std::string) that might throw it.
But if you want to be able to catch and recover from a bad_alloc, you need to ensure that none of your exception copy constructors can cause one. If you're writing a library that other applications will use, you should not assume that the application does not want to handle bad_alloc.
C++11 make this much easier by using move constructors (instead of copy constructors) where possible. Since the move constructor for std::string never throws exceptions you can safely use a std:string in your exception type as long as you properly implement move constructors, and ensure that they are used. Note that the initial construction of the object to be thrown in a throw expression is NOT part of the exception throwing process, so that constructor can throw an exception without causing a double exception (and terminate()). So if you have:
throw some_function();
some_function might throw an exception (such as bad_alloc) without returning an object to be thrown and that's fine. If it doesn't throw an exception (and returns a valid object), the move constructor for the exception type will be used (if available) for the exception throwing process, and that move constructor must not throw an exception.
Completely independent of the above, whenever you call new you need to ensure that exactly one spot will call delete in every possible case, or you'll leak memory (or crash from a double delete). This becomes tricky any time you have a function that calls new and then does something else that might throw an exception (such as call new again). If this happens in a constructor, the destructor for the object will not be called (though destructors for base classes and fields will be), so you can't do the cleanup in the destructor as you are trying to do with your example.
Fortunately std::unique_ptr exists to make this much easier. If you write your exception class as:
struct xexception {
std::unique_ptr<int[]> ttt[10];
xexception() {
ttt[0].reset(new int[0xfffffffL]);
ttt[1].reset(new int[0xfffffffL]);
ttt[2].reset(new int[0xfffffffL]);
ttt[3].reset(new int[0xfffffffL]);
ttt[4].reset(new int[0xfffffffL]);
ttt[5].reset(new int[0xfffffffL]);
ttt[6].reset(new int[0xfffffffL]);
ttt[7].reset(new int[0xfffffffL]);
ttt[8].reset(new int[0xfffffffL]);
ttt[9].reset(new int[0xfffffffL]);
}
};
it should work and not leak memory.
While I think not using std::string for core, fundamental exceptions may be a good guideline, I don't think user-facing libraries/applications should necessarily follow this.
There may be other reasons, but you hit on the primary one: you'd like to indicate to the user (or developer) contextually meaningful information, which you often cannot do with a mere literal string. A dynamic allocation must occur in order to do this. If, for some reason, you had a bad_alloc, you're probably already hosed to begin with, so it doesn't buy/lose you anything.
Edit:
By the way: the destructor of std::exception is marked as virtual for a reason!
Related
What is the difference between these two:
try
{
MyClass* tmp=new MyClass;
return tmp
}
catch (...)
{
cout << "Error";
}
and
try
{
return new MyClass;
}
catch (...)
{
cout << "Error";
}
I think that if an error happened in the second one it will return immediately and not catch the error, right?
They do exactly the same thing.
And will (most likely) generate exactly the same code.
The first one though is helpful if you are using an interactive debugger. After the new is complete it is easier to just check the object (by click on tmp (or typing print tmp into the debug console)) and see if was initialized correctly.
Not something you do often but it comes up.
The two pieces of code will accomplish the same thing. The first one will more easily allow you to see the value of tmp in a debugger or add a line to print its value while debugging.
Unrelated to your question: why are you using new? It is generally better to use std::unique_ptr and std::make_unique instead of a raw pointer and new. std::unique_ptr will also refer to a dynamically allocated instance of MyClass, but will automatically call delete when it goes out of scope, making it less likely for you to have memory leaks in your program.
Both have same functions.
For the try{ } and catch(...) will also work fine in case there are error during allocating memory for MyClass.
But I personally prefer the new method, as sometimes I will do something before return the class.
1) Do we need to have a pointer validation for following code in cli. Is it good to have?
NameClass NameString^ = gcnew NameClass();
if (NameClass)
{
// some process
2) If we created a memory in one function and passing as pointer to other do we need to have validation ?
foo()
{
try {
NameClass *pNameString = new NameClass();
foo_2(pNameString);
} catch(std::bad_alloc &error)
{
std::cout << error.what() << std::endl;
}
}
foo_2(NameClass *pNameString)
{
if (pNameString) // do we need to validate here ?
{
// some stuff
}
}
3) Do we need to validate locally created object in reference passing ?
NameClass objNameClass;
foo(&objNameClass);
foo(NameClass *objNameClass)
{
if (objNameClass) // do we need to validate here ?
{
It's just as unnecessary just after a gcnew as it is after a new. It's only necessary if you use C allocators like malloc for some reason. The C++ and C++/CLI constructs use exceptions for unsuccessful object creations, unlike the C functions which return a null pointer.
In plain C++, new will throw std::bad_alloc if memory cannot be allocated. In C++/CLI, gcnew will throw System::OutOfMemoryException in that case.
Is most cases, you probably should let the exception propagate and kill your program, because it's probably doomed anyway.
In your second example, you may want to validate the pointer in foo_2 only if you expect someone to call foo_2 with a null pointer, and when that is a valid usage. If it's invalid usage to pass it a null pointer as an argument, then you have a bug and should probably let your application crash (instead of letting it corrupt your data for instance). If foo_2 is only visible to the code which calls it immediately after allocation, it's unnecessary as it won't ever be null.
Same for the third example. The contract/documentation of your function should specify whether it is valid to call it with a null pointer, and how it behaves.
And please, don't ever write that:
catch(std::bad_alloc &error)
{
std::cout << error.what() << std::endl;
}
If you have a low memory condition on a regular object allocation, just let your program die. Trying to cure it that way won't get you very far.
The only place when such code would be acceptable IMHO is when you're trying to allocate a potentially big array dynamically, and you know you can just cancel that operation if you're unable to do so. Don't attempt to catch allocation errors for every allocation, that will bloat your code and lead you nowhere.
In previous programs I have used the following code to check for memory allocation failures, usually without thinking about alternatives:
int* p_int = new int[10];
if(!p_int)
{
// We failed, so exit
return EXIT_FAILURE;
}
This method is also documented here.
I found here a reference for the syntax:
p_int = (nothrow) new int[10];
Which suggests that if the programmer does not include the nothrow "argument" to new, then the check for nullptr is invalid? Is this correct? Or is it OS dependent?
As I understand it, there is little point putting new in a try-catch block unless you can actually recover from it because of the overhead associated with this. Is this also correct?
Checking for nullptr after a new is useless because a failed new does not set the pointer to nullptr
int* p_int = new int[10];
if(!p_int)
{
// error handling
}
Rather a failed new will throw a std::bad_alloc, so if you want to try to deal with it, you need to try and catch
try
{
int* p_int = new int[10];
}
catch (const std::bad_alloc& e)
{
std::cout << "Allocation failed: " << e.what();
// deal with it
}
Yes, unless a no-throw version of new was used (and it was not overloaded to do something else!) it will never return null, and instead will throw an exception.
And as for omnipresent check for null when dealing with pointers, this is usually a misguided thing. At most, it should be limited to debug builds. Since null pointers are just a narrow subclass of generally bad (non-dereferenceable) pointers, and they seldom appear in non-debug builds, checking for nulls is just CPU warm-up. For instance, library functions usually do not check their inputs for nulls.
I have created a class and I want not to create the object if one member is empty. These are the code lines:
#include "verification/CVerifObj.hpp"
VerifObj::VerifObj(const fs::path& imgNameIn)
{
m_image = cv::imread(imgNameIn.string());
AnalyseCSV csv;
m_plateContour = csv.getPlateRegion(imgNameIn); // search for the csv file and load the values
if (m_plateContour.empty()) // throw exception if empty csv
{
throw EmptyContourException(imgNameIn.string());
}
m_imageName = imgNameIn.string();
}
VerifObj::~VerifObj()
{
// are these enough for destructor?
m_image.release();
m_plateContour.clear();
}
Is this OK, or shall I do something more? How shall I be sure that if the exception is thrown the object is not created?
I have the following lines of code for ensuring it:
for(fs::directory_iterator iter(folderIn); iter != end; ++iter)
{
if(!fs::is_regular_file(iter->status()))
{
continue;
}
std::string extension = iter->path().extension().string();
if(targetExtensions.find(extension) == targetExtensions.end())
{
continue;
}
try
{
VerifObj verifObj(iter->path());
verifObjVecRet.push_back(verifObj);
}
catch (EmptyContourException& ece)
{
continue;
}
catch (CSVException &csve)
{
continue;
}
}
Hopefully, m_image and m_plateContour (and any other non-trivial members of your class) are properly designed RAII types, with destructors that clean up any resources they might have.
In that case, your class won't need a destructor at all, and all the members will be properly destroyed automatically if your constructor throws - there's no need to take any action there.
However, the presence of the destructor implies that they might be evil types which do need manually cleaning up before destruction. In that case, fix them.
If you can't fix them for some reason, you'll need m_image.release(); before throwing. You'll also need a large coffee supply, as classes like that will lead to long debugging sessions trying to fix memory leaks.
The short answer is, throwing stuff in the constructor is dangerous.
First, lets define the design problem: you have a class that can fail to initialize. If the class fails to initialize, it cannot be used (will cause additional errors if used), so the class failing is considered a "critical failure", atleast where the class is concerned.
In a nutshell, what we want to avoid is letting a user use a class that failed to initialize.
Imagine the following situation:
class A
{
public:
A()
{
stuff1 = malloc(100);//some dynamic memory allocation
throw "This throw is crazy";
stuff2 = malloc(100);//some dynamic memory allocation
}
~A() {free(stuff1); free(stuff2);}
private: void* stuff2;void* stuff2;
};
int main(int argc, char** argv)
{
A a;
}
Once you throw in the constructor, what happens to stuff? well, it is an instant memory leak. The destructor is never called. Which is baaaad. If you handle the exception:
int main(int argc, char** argv)
{
try
{
A a;
}
catch(...)
{
//can't do much here
}
}
You've lost the reference to A, which is a nightmare. So some people try to get away with this instead (Up front, it is still bad)
int main(int argc, char** argv)
{
A* a;
try { a= new A();}
catch(...){delete a;}
}
But that is just as bad. You may still have a reference to a (and the memory directly pointed to by a will not leak) but a is now in an unknown state...you'll still have to delete it some day, and the free for stuff2 failed.
One way to get around this is to make your constructor and destructor alot smarter. Catch any exceptions that can be thrown in the constructor, and clean up the object, returning a "zombie" object. And have the destructor easily be able to check for the zombie object. I find this method to be more complicated.
A better way to some is to use an initializer:
class A
{
public:
A() {stuff1=null; stuff2=null;}
void init()
{
stuff1 = malloc(100);//some dynamic memory allocation
throw "This throw is crazy";
stuff2 = malloc(100);//some dynamic memory allocation
}
void destroy() {if (stuff1) {delete stuff1; stuff1=NULL;} if (stuff2) {delete stuff2; stuff2=NULL;}}
~A() {destroy();}
};
I don't like this because you still get "zombie" objects, and have all the added upkeep of calling init and destroy. Going back to the original problem, both a smarter constructor and providing initalizers still don't solve the nutshell statement: the end user can still (pretty easily, in fact) use an instance that is in an unknown state.
I like to follow a pseudo RAII (Resource Acquisition Is Initialization) here: what you want to to ensure that, if you have a reference to an object, it is a valid reference. Else, there should be no memory leaks. The best way (IMHO) to achieve this is to use a factory method, and keep all the initializes private.
class A
{
public:
~A() {destroy();}
static A* MakeA()
{
A* ret = new A();
try { ret->init();}
catch(...)
{
delete ret;
return NULL;
}
return ret;
}
private: void* stuff1,*stuff2;
A() {stuff1=null; stuff2=null;}
void init()
{
stuff1 = malloc(100);//some dynamic memory allocation
throw "This throw is crazy";
stuff2 = malloc(100);//some dynamic memory allocation
}
void destroy() {if (stuff1) {delete stuff1; stuff1=NULL;} if (stuff2) {delete stuff2; stuff2=NULL;}}
};
Now the user can never make a valid reference to a failed object, which is nice.
Protips:
Exception handling is slow. If you expect this to happen often, or don't think that it will be a fatal error, use error codes in your init statements. Error codes in the factory method can give the user more info as well.
I used raw pointers in this answer cuz I'm too lazy to write all those characters in an answer. Always use smart pointers and this becomes even easier. Juggling raw pointers is only for the criminally insane. (CLARIFYING USE SMART POINTERS)
Edit: clarified what I'm lazy about
int main()
{
cout<<"Enter n";
cin >> n;
int * a = new int[n];
a = foo(n);
free(a);
return -1;
}
int * foo(int n)
{
int * a = new int [n];
if(!a) // what should I return here if allocation of a fails
{}
free(a);
}
In the code above I am trying to catch the return value of an function from main, the return type of the function is a pointer . However I am allocating memory dynamically . So , what should I return if my memory allocation fails ... any special symbol like NULL .
P.S - Its a very basic question and could not formalize my question to any succinct form for to search over Google.
Edit: Thanks all of you guys . I have solved my problem .
It is a custom to return NULL in case of allocation failure from functions which allocate their own memory and return pointer to it. See for example strdup(). Note that operator new throws std::bad_alloc if it fails to allocate memory, so you may need to catch this if you want to return NULL or alternatively, you can let std::bad_alloc propagate out of the function.
Note however, that it is not always wise to return such pointers since it raises the issues of ownership and increases the likelihood of memory leaks.
You may find that sticking to the RAII idiom makes your code easier to reason about and less error prone. One consequence of RAII idiom is that allocation and deallocation are done by the same code unit.
In your particular situation you allocate the array in main() so you may pass the pointer to it to foo() and deallocate memory also in main().
Also, if you use new to allocate, you should use a proper version of delete to deallocate (here delete[] since you allocated an array). You use free() to deallocate memory allocated with malloc() and friends.
operator new throws exception (except nothrow operator new), so, you can catch this exception and return null pointer, or rethrow, or throw other exception.
The newoperator throws a bad_alloc exception if allocation fails. So you can catch this exception and handle the error.
For exemple:
#include <new> // std::bad_alloc
int* foo(int n)
{
int* a(new int[n]);
return a; // I guess you want to return the address stored in a
}
int main()
{
try
{
int* a(foo(n));
}
catch(std::bad_alloc& ba)
{
// Handle here the error (e.g: std::cerr << "Allocation failed:" << ba.what() << std::endl;)
}
return 0;
}
EDIT1: If you use C++11 features, forget NULL or 0 and use nullptr instead!
If your return value is a pointer then NULL is the most logical value in the case of an error. You could also look at raising an exception, but for now returning NULL should suit your needs.
The new operator would throw a bad_alloc exception in such a case and probably you should catch it and handle it according to your requirements (http://www.cplusplus.com/reference/std/new/bad_alloc/)
It can return any value. The thing is that then you have to treat it correctly.
if(!a) // what should I return here if allocation of a fails
{ return NULL;}
this will imply allocation failed i.e. by returning a NULL pointer.