I have been trying to fix a potentially sketchy use of void* casting in a task scheduling application for weeks now. Note that I am NOT getting a compiler error, but the scheduling program crashes after a few hours (for some unknown reason). Consider the following code snippets from the program:
In main:
CString* buffer = new CString(temp);
parameters.set("jobID", (void *) buffer);
runJob(parameters);
Also, VGridTaskParam class is as follows:
class VGridTaskParam{
map<CString, void *> p; // maps from CString to a pointer that is not known
public:
void * get(CString name){
return p[name]; // returns the map value of the name which is an unknown pointer
}
void set(CString name, void * data){
p[name] = data; // sets the mpa value given a particular key
}
};
Snippet of some work in runJob(VGridTaskParam parameters) function is:
void runJob(VGridTaskParam parameters)
{
CString JIDstr; // job ID string
//get job ID as CString
CString* pJID = (CString*)parameters.get("jobID");
JIDstr = CString(*pJID);
delete pJID; ******************************
}
Some questions: does the last delete line (marked with several asterisks) delete the memory allocation created in the main program? Is my use of void* casting warranted in this situation. Note that whenever I run a job, I spawn a new thread. Can someone suggest a potential fix to this problem? What should I look at to fix this problem?
does the last delete line (marked with several asterisks) delete the memory allocation created in the main program?
Yes.
Is my use of void* casting warranted in this situation?
No, that is superfluous. Any pointer can be cast to void* without the explicit cast.
Can someone suggest a potential fix to this problem? What should I look at to fix this problem?
I can't suggest a fix without an MCVE.
A few possible issues:
what will happen if you write twice to same key? This will cause a memory leak.
there are few possible solutions, like:
void set(CString name, void * data){
if(p[name]!=NULL)
delete p[name];
p[name] = data; // sets the mpa value given a particular key
}
Another thing: Are you running multi-threaded or single threaded? for multi-threaded you should synchronize the get and set methods to prevent pointer changes in a middle of action.
And finally, what happen if key not found? you should check the returned pointer. also remove from the set or null it after usage.
void runJob(VGridTaskParam parameters)
{
CString JIDstr; // job ID string
//get job ID as CString
CString* pJID = (CString*)parameters.get("jobID");
if(pJID){
parameters.set("jobID",NULL);
JIDstr = CString(*pJID);
delete pJID; ******************************
}
}
I see two things that looks a bit surprising to me.
1) runJob takes parameters of type VGridTaskParam by value. Maybe you want a reference instead. That can't explain the crash, though.
2) You never seem to remove anything from the map even though you delete the memory associated with the pointer. So there is a risk that you'll use the pointer value later on. Either as a dereference or as a double delete.
3) You don't implement any check for the key being present in the map.
Your delete is correct. It deletes an allocated block of memory of the size of the pointer's type at the pointer's address. So when you allocate a CString with new you will delete the exact same amount of memory.
The hang up is when you delete unallocated memory. There are several ways I could see this happening in your current code:
runJob requests an key not in the map (this will return a default initialized CString* as the newly created value.)
You call runJob on a previously deleted item in the map (this value would already be deallocated and deleting it again would be illegal.)
We can't see all your code but if there is the potential to delete these pointers elsewhere there could also be a double cleanup problem there.
You should code your map more defensively, for example:
const void* get(const CString& name) const {
return p.find(name) == p.cend() ? nullptr : p[name]; // returns the map value of the name which is an unknown pointer
}
void set(const CString& name, void* data) {
void* toOverwrite = get(name);
if(toOverwrite != nullptr) {
delete toOverwrite;
}
p[name] = data; // sets the mpa value given a particular key
}
void remove(const CString& name) {
if(p.find(name) != p.end()) {
p.erase(name);
}
}
In your function you'd need to change to testing if the return of get was a nullptr before operating on the result, and rather than delete you'd need to call remove. This keeps all modification of p local to the class, thereby guaranteeing correct maintenance of the map.
Related
The code below works fine, but if I try to access the private member variable m_sal in the function fun(), it leads to segmentation fault.
Can any one explain what's the reason ?
class Emp
{
int m_sal;
public :
void fun(char* name)
{
std::cout<<"Name :"<<name<<std::endl;
}
};
int main()
{
Emp *e = NULL;
e->fun("Hi");
return 0;
}
Calling a method by a NULL pointer - as you are doing - is undefined behaviour. So it may crash, not crash, do anything.
First might want to change your method's signature to read
void fun (const char* name) const;
Converting from "Hi" to char * is deprecated and const correctness highly recommended. Your crash is caused as people mentioned by calling your method on a null pointer. Try
Emp * e = new Emp;
e->fun("Hi");
instead.
Of course it crashes.
Emp *e = NULL;
creates a pointer which happens to be a null pointer (because of = NULL , but I am sure many of us would prefer = nullptr), so there is no memory allocated for the object it is pointing to. You need to create an object this pointer will point to:
Emp* e = new Emp;
and now you can use it.
The exact reason for the crash is that the application is trying to fetch a value from a very low memory address (pointer's value is 0, for some cases add a few padding bytes maybe for the correct memory layout of the C++ object, but highly possible in this case it just wants to read the memory at address 0) which in most cases and OS's is reserved to be used by the system.
In your code, e is a pointer, not an actual instance of an object. You can either have:
Emp e;
e.fun("Hi");
//No need to clean up stack variable
OR
Emp *e = new Emp;
e->fun("Hi");
delete e; //don't forget to clean up!
What you have is undefined behavior because of using a null pointer to call a function.
I have a class with a member function mBoundingBox made up of the following struct
typedef struct
{
unsigned int xMin;
unsigned int yMin;
unsigned int xMax;
unsigned int yMax;
} boundingBox;
class CImgProc
{
public:
CImgProc(void);
virtual ~CImgProc(void);
...
boundingBox *mBoundingBox;
...
}
In code I allocate the member:
mBoundingBox = new boundingBox [mBlobCnt];
piddle around with it (don't assign any pointers to it, just using array indexing), then, when I exit I:
if (mBoundingBox != NULL) delete [] mBoundingBox;
and this is causing an error.
Any input?
Updated info. The error does occur at termination in the destructor. The message generated by VS is:
Windows has triggered a breakpoint in ProcImage.exe.
This may be due to a corruption of the heap, ...
This may also be due to the user pressing F12 while ProcImage.exe has focus.
The output window may have more diagnostic information.
I am setting the pointer to NULL in the constructor and then allocating (with new) when I need to. The pointer is valid, but apparently not on the heap (break lands in dbgheap.c).
Once I allocate the memory, I don't happen to do any pointer magic with it. In this case I am looping through an image and gather stats. Then I use the stats stored in this memory to draw back into my image, but, again, in a rather brute force manner, so nothing else makes use of this memory.
It is legal for me to use new to create an array of structs isn't it?
Doh!!! Sorry to waste ya'lls time. I dug back in and discovered that my creation and destruction are fine, but somewhere in the middle I set the value of mBoundingBox[X]. whatever where it turns out X is the dim of the array created.
Typical user error, just a surprising place for the bug to show up.
Most probably you are deleting your array twice. To manage it better use
delete[] mBoundingBox;
mBoundingBox = 0;
instead of
if (mBoundingBox != NULL) delete [] mBoundingBox;
or even better use a smart pointer.
first of all the following check is wrong
if (mBoundingBox != NULL) delete [] mBoundingBox;
new does not returns NULL when it fails to allocate memory, rather it throws an exception.
use nothrow version of "new" if you want to proceed like you are doing. In nothrow version new will return NULL instead of throwing an exception.
mBoundingBox = new (std::nothrow) boundingBox [mBlobCnt];
Tutorials, searches, and the dim memory of my C++ formal education have left me clueless as to where I should use delete when I'm using a dynamically allocated object pointer in a loop, such as:
// necessary files are included, this code is within main
T * t;
t = foo.getNewT();
while (!t->isFinalT()) {
// print t stuff
delete t; // is this where I should delete t?
t = foo.getNewT();
}
delete t;
This lack of knowledge has become particularly troublesome on a recent class project. On my laptop (Linux Mint, g++ Ubuntu/Linaro 4.7.3-1ubuntu1) the code ran fine without the delete statement and crashed when I added the delete statement. On the school server (Solaris, g++ (GCC) 3.4.5), the code segfaulted after a few iterations without the delete statement, and runs fine when I add the delete statement.
How do I handle this kind of loop properly so that it will run in most environments?
Additional Info:
The error on my laptop occurs when the program reaches the delete request:
*** Error in 'program': free(): invalid next size (fast):...
Some of the other code:
// T.h
class T {
int id;
int num;
int strVarPos;
char * strVar;
public:
T();
~T();
// + misc. methods
}
// T.cpp
T::T() {
id = 0;
num = -1;
strVarPos = 0;
char * strVar = new char[11];
strVar[0] = '\0'
}
T::~T() {
delete [] strVar;
}
// Foo.cpp
T * Foo::getNewT() {
T * t = new T;
// populate T's fields
return t;
}
Resolution:
Because a simple test with just T * t and the loop worked ok, I ended up reconstructing the project starting from blank and adding one class at a time, to see when the problem would appear. Turns out that I had added additional content into a dynamically allocated array elsewhere in the program without updating the size constant I was using to initialize the array.
Evidently the school server could only handle the resulting memory discrepancy without crashing if I was making sure to delete the pointers properly (the program didn't run long enough to cause a significant memory leak in my tests), while my laptop wouldn't notice the memory discrepancy until I attempted to call delete (and then would crash).
Assuming that foo.getNewT() is handing ownership of the memory over to the caller:
T * t;
t = foo.getNewT();
//while (!t->isFinalT()) // if foo.getNewT ever returns NULL, this will be UB!!!
while (t != nullptr && !t->isFinalT())
{
// ...
delete t; // if you now own it and are no longer going to use it, yes, delete it here
t = foo.getNewT();
}
delete t; // you also need this one to delete the "final" t
However, you can avoid having to do it yourself by using std::unique_ptr:
std::unique_ptr<T> t;
t.reset(foo.getNewT());
while (t && !t->isFinalT())
{
// ...
t.reset(foo.getNewT());
}
Alternatively, you could rewrite the loop to flow a bit better:
std::unique_ptr<T> t;
do
{
t.reset(foo.getNewT());
if (t)
{
// do stuff with t
}
} while (t && !t->isFinalT());
the code ran fine without the delete statement and crashed when I
added the delete statement.
Are you sure getNewT is handing ownership of the T* to you? If you delete it, and then it tries to delete it later, you will end up with a heap corruption. If it is handing ownership over to the caller, and you do not delete it, you get a memory leak.
With the additional information in your edit:
char * strVar = new char[11];
That line is unnecessary if you declare strVar as either a std::string or a char[11]. If you attempt to copy any of those T objects, you'll be using the default copy constructor (as you have not defined one), which will do a shallow copy (that is, copy the value of the pointer for strVar). When you delete 2 Ts that are both pointing to the same memory location, you get a heap corruption. The most robust solution would be to declare strVar as a std::string.
The problem is not the delete. You have put it in the right place. It's more likely something else you are doing that is causing undefined behaviour.
Note that you should have a delete t after the loop as well (to catch the last one). This is assuming that foo.getNewT() always returns a valid pointer (which it must, because you never check if it is NULL).
You should delete a dynamically allocated memory when you no longer need it. If you want t to hold its value inside the for loop, then delete it outside the loop otherwise delete it inside.
However, the best thing to do is to use std::unique_ptr when you really have to use pointers . It will take care of deallocating the memory itself when all references to the memory are destroyed. You should try to avoid allocating memory as much as you can. Use STL containers if they fit the job.
I think when you delete t you are deleting the real object inside your structure.
Maybe that what is causing the problem.
I am wondering how one would go about returning a new object from a C++ function. For example, I have a SQLite wrapper which used to mix in Objective-C and I modifying it to be purely C++.
So, for example:
list<char*> * SqliteWrapper::RunQuery(const char *query)
{
list<char*> * result = new list<char*>();
//Process query
return result;
}
the issue that I can see in this, is that who owns the object? The calling class or the class that created the object? What is worse, is that this is very prone to memory leaks. If the caller object does not delete the newly created object, the app will end up with a memory leak.
Now that I think about this, this would make a lot of sense:
int SqliteWrapper::RunQuery(const char *query, list<char*>& result)
{
//Process query
return errorCode;
}
Are there any other approaches to this? I have been a C# programmer for a while and only now am starting to work heavily with C/C++.
Many programmers do this:
If it is a pointer that is returned, I am being given the object's identity (it's location in memory is unique) I must manage that. I am responsible for deleting it.
(Pointer = my job)
references however let you pretend you are being passed the object, to look at and use. you are not responsible for deleting these, something else is.
BUT:
"Naked pointers" may be frowned upon for code like this (it's very subjective) so some would say use a "unique_ptr" to that, these can be moved, and delete what they point to when deleted (unless the stuff is moved out of them), by returning one and not using it, it will be deleted.
(tell me if you want me to flesh this out, see also "shared_ptr" if multiple things have a pointer, this will delete what it points to when the last shared_ptr pointing to it is deleted)
Addendum 1
unique_ptr<list<char*>> SqliteWrapper::RunQuery(const char *query)
{
list<char*> * result = new list<char*>();
//Process query
return make_unique<list<char*>>(result);
}
Remember you can only move, not copy unique_ptrs
Well. You are right.
First example would be a bad style, since in such a code is hardly readable and it is hard to track bugs in it.
Usually people use the second approach with reference.
In the same way you can use pointer, allocating the return object before function call.
Third approach would be to use class instead of function. It is convinient if your function does complicated process with many parameters. In this case you store result as a data member of the class and ownership is obvious:
class SqliteWrapper {
...
class ProcessQuery {
public:
ProcessQuery():fQ(0),fP1(0){}
SetQuery(const char *query){ fQ = query; }
SetP1(int p1){ fP1 = p1; }
...
list<char*> GetResult(){ return fR; } // copy
int Run();
private:
const char *fQ;
int fP1;
...
list<char*> fR;
}
...
}
int SqliteWrapper::Process::Run()
{
//Process query
return errorCode;
}
Say I have a pointer like this:
int *thingy;
At some point, this code may or may not be called:
thingy=new int;
How do I know if I can do this:
delete thingy;
I could use a bool for every pointer and mark the bool as true whenever the I use new, but I have many pointers and that would get very unwieldy.
If I have not called new on thingy, calling delete on it would likely cause a crash, right?
I searched around quite a bit but could find no answer that clearly fit my situation.
EDIT: I need to be able to delete the pointers as many times as I like without the pointers necessarily pointing to any data. If this is impossible I'll have to re-write my code.
Initialize it to NULL always
int *thingy = NULL;
and then
delete thingy;
thingy = NULL;
is valid even if thingy is NULL. You can do the delete as many times as you want as long as thingy is NULL delete will have no unwanted side effects.
There's no built-in way to tell if a particular pointer value is deleteable. Instead you simply have to design the program to do the right thing, preferably by carefully designing resource ownership policies in line with your requirements and them implementing them with something like RAII.
Given appropriate RAII types you will not need to scatter deletes or other resource management commands around your code. You will simply initialize and use objects of the appropriate types, and leave clean up to the objects themselves. For example if the RAII type unique_ptr corresponds to an ownership policy you want to use then you can manage an object this way:
unique_ptr<int> thingy {new int};
// use thingy ...
There's no need to manually cleanup, because unique_ptr takes care of that for you.
On the other hand if you try to manage resources directly you end up with lots of code like:
int *thingy = nullptr;
// ...
thingy = new int;
try {
// something that might throw
} catch(...) {
delete thingy;
thingy = nullptr;
throw;
}
delete thingy;
thingy = nullptr;
There is no builtin C++ tool to identify if a pointer points to heap data and can safely deleted. It's safe to delete a NULL pointer and you can set every pointer whose data has been deleted to NULL. But this doesn't help to differentiate between pointers to heap data and pointers to other data or to code.
When your operation system starts a process it will locate the code and data sections to specific data areas. In Windows this is partially controlled by the PE header of the EXE file. Therefore the actual address of the memory regions may vary. But you can identify where theses regions are located:
code
bss
data
stack
heap
After obtaining the address range for each region you can differentiate between a pointer to the heap data (where delete is appropriate) and a pointer to stack data. This allows you to differetiate between deleteable and data whose pointer you must not delete.
Write a wrapper class that does the tracking for you, eg:
template<typename T>
class ptr_t
{
private:
T* m_ptr;
bool m_delete;
ptr_t(const ptr_t&) {}
ptr_t& operator=(const ptr_t&) { return *this; }
public:
ptr_t()
: m_ptr(NULL), m_delete(false)
{
}
ptr_t(T *ptr, bool del)
: m_ptr(ptr), m_delete(del)
{
}
~ptr_t()
{
reset();
}
void assign(T *ptr, bool del)
{
if (m_delete)
delete m_ptr;
m_ptr = ptr;
m_delete = del;
}
void reset()
{
assign(NULL, false);
}
operator T*() { return m_ptr; }
bool operator!() const { return (!m_ptr); }
};
typedef ptr_t<int> int_ptr;
.
int_ptr thingy;
...
thingy.assign(new int, true);
...
thingy.reset();
.
int i;
int_ptr pi;
...
pi.assign(&i, false);
...
pi.reset();