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.
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.
First off, this is not a duplicate. My question is how to do it with dynamic memory. The reason this is distinct is because my delete[] is hanging.
So, here's what I have:
class PacketStrRet {
public:
PacketStrRet(char p_data[], int p_len) : len(p_len) {
data = new char[p_len];
memcpy(data, p_data, p_len * sizeof(char));
}
~PacketStrRet() {
delete[] data;
data = nullptr;
}
char* data;
int len;
};
And yes, I'm aware that my code is not using the best practices. I'll clean it up later.
The problem I'm having is in the DTOR. That delete is hanging forever. The data being passed in to the CTOR is not dynamic memory, so I need to make it dynamic so things don't go out of scope. p_len holds the correct amount of data, so there's no problem there.
From what I've read, memcpy seems to be the most likely culprit here. So how do I copy a string that is not null-terminated to dynamic memory, and then still be able to delete it later?
Thanks.
The problem is not the delete, only everything that comes before and even that would be ok if there didn't occur any problems.
class PacketStrRet {
// Use RAII
std::unique_ptr<char> data; // I own this data and will destroy it.
// now the parent class is also only movable, use shared_ptr if you can't live with that.
int len;
public:
PacketStrRet(
// <RED ALERT>
char p_data[], int p_len // user can lie to us.
// </RED ALERT>
) try : // function try block, se 1)
len(p_len), data(new char[p_len]) {
memcpy(data, p_data.get(), p_len * sizeof(char));
} catch(const std::exception& e) {
std::cerr << "arg=" << arg << " failed: " << e.what() << '\n';
}
~PacketStrRet() {
// unique_ptr takes care of memory management and garbage collection.
}
// access functions
};
Now the possible errors you could make to blow the code up.
You could have copied the object, essentially making two owning raw pointers to the same data. This would blow up at delete, you coudl use memory-sanitizer / valgrind to confirm this happens. Use smart pointers to save you the trouble, the unique pointer should cause a compiler error if you tried to copy, unless you memcpy the entire structure ignoring the copy/assignment constructors.
You could give the wrong len to the constructor, what is the source of the data and len? Valgrind / memory-sanitizer can save you.
The memory corruption could happen in a totally different place. Valgrind / memory-sanitizer can save you.
In case valgrind mem-san are too much, you can try to make a check for double delete, if you make a counter in c'tor and d'tor and if it ever goes to negative you have your error.
In this class your at least missing a copy constructor. Check up on rule of 3, 5, 7 and 0 (zero) to find out how many you need.
1) http://en.cppreference.com/w/cpp/language/function-try-block
Try to use std:: copy(). It will be like this:
std::copy(p_data, p_data + p_len, data).
Deleting the double pointer is will cause the harmful effect like crash the program and programmer should try to avoid this as its not allowed.
But sometime if anybody doing this then i how do we take care of this.
As delete in C++ is noexcept operator and it'll not throw any exceptions. And its written type is also void. so how do we catch this kind of exceptions.
Below is the code snippet
class myException: public std::runtime_error
{
public:
myException(std::string const& msg):
std::runtime_error(msg)
{
cout<<"inside class \n";
}
};
void main()
{
int* set = new int[100];
cout <<"memory allcated \n";
//use set[]
delete [] set;
cout <<"After delete first \n";
try{
delete [] set;
throw myException("Error while deleting data \n");
}
catch(std::exception &e)
{
cout<<"exception \n";
}
catch(...)
{
cout<<"generic catch \n";
}
cout <<"After delete second \n";
In this case i tried to catch the exception but no success.
Pleas provide your input how we'll take care of these type of scenario.
thanks in advance!!!
Given that the behaviour on a subsequent delete[] is undefined, there's nothing you can do, aside from writing
set = nullptr;
immediately after the first delete[]. This exploits the fact that a deletion of a nullptr is a no-op.
But really, that just encourages programmers to be sloppy.
Segmentation fault or bad memory access or bus errors cannot be caught by exception. Programmers need to manage their own memory correctly as you do not have garbage collection in C/C++.
But you are using C++, no ? Why not make use of RAII ?
Here is what you should strive to do:
Memory ownership - Explicitly via making use of std::unique_ptr or std::shared_ptr and family.
No explicit raw calls to new or delete. Make use of make_unique or make_shared or allocate_shared.
Make use of containers like std::vector or std::array instead of creating dynamic arrays or allocating array on stack resp.
Run your code via valgrind (Memcheck) to make sure there are no memory related issues in your code.
If you are using shared_ptr, you can use a weak_ptr to get access to the underlying pointer without incrementing the reference count. In this case, if the underlying pointer is already deleted, bad_weak_ptr exception gets thrown. This is the only scenario I know of when an exception will be thrown for you to catch when accessing a deleted pointer.
A code must undergo multiple level of testing iterations maybe with different sets of tools before committing.
There is a very important concept in c++ called RAII (Resource Acquisition Is Initialisation).
This concept encapsulates the idea that no object may exist unless it is fully serviceable and internally consistent, and that deleting the object will release any resources it was holding.
For this reason, when allocating memory we use smart pointers:
#include <memory>
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
using namespace std;
// allocate an array into a smart pointer
auto set = std::make_unique<int[]>(100);
cout <<"memory allocated \n";
//use set[]
for (int i = 0 ; i < 100 ; ++i) {
set[i] = i * 2;
}
std::copy(&set[0], &set[100] , std::ostream_iterator<int>(cout, ", "));
cout << std::endl;
// delete the set
set.reset();
cout <<"After delete first \n";
// delete the set again
set.reset();
cout <<"After delete second \n";
// set also deleted here through RAII
}
I'm adding another answer here because previous answers focus very strongly on manually managing that memory, while the correct answer is to avoid having to deal with that in the first place.
void main() {
std::vector<int> set (100);
cout << "memory allocated\n";
//use set
}
This is it. This is enough. This gives you 100 integers to use as you like. They will be freed automatically when control flow leaves the function, whether through an exception, or a return, or by falling off the end of the function. There is no double delete; there isn't even a single delete, which is as it should be.
Also, I'm horrified to see suggestions in other answers for using signals to hide the effects of what is a broken program. If someone is enough of a beginner to not understand this rather basic stuff, PLEASE don't send them down that path.
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'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!