How do I write a generic function to delete any valid pointer? - c++

Following is my code snippet. I am trying to write generic function to check whether pointer is valid and deleting it.
#include <windows.h>
#include <vector>
#include <map>
#include <string>
using namespace std;
struct testStruct
{
int nVal;
_TCHAR tcVal[256];
testStruct()
{
wmemset(tcVal, 0, _countof(tcVal));
}
};
void deletePointer(void *obj)
{
if (obj)
{
delete obj;
obj = NULL;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
testStruct *obj = new testStruct;
wstring *strVal = new wstring();
vector<wstring> *vecVal = new vector<wstring>;
map<wstring,wstring> *mapVal = new map<wstring, wstring>;
//My business logic goes here.
//Finally after all business logic, clearing allocated memory.
deletePointer(obj);
deletePointer(strVal);
deletePointer(vecVal);
deletePointer(mapVal);
return 0;
}
While I am not facing any compilation or runtime error, just wanted to confirm, if this is the right way to check and delete multiple points. I don't want to check individual pointer whether it is valid or not before deleting. So calling generic function.
Thanks for your suggestions in advance.
Compilation and runtime errors are not present. Just need confirmation, if this is right way or is there a better way to do this.

No, it's both incorrect and unnecessary
If your compiler doesn't report error on this code, crank up warnings: https://godbolt.org/z/7ranoEnMa. Deleting a void* is Undefined Behaviour, you cannot predict what will be the result. If it's currently not crashing, it will likely crash at some random other use when you will least expect it.
It's unnecessary, because it's perfectly fine to delete nullptr; and your function only checks against that. If you wanted to check if the pointer is actually valid like Nathan Pierson suggests in comment (and you don't assign nullptr to them consistently), that's not possible. You are responsible for your memory management, no if can help if you don't do that correctly throughout the program.
And it's also not necessary, because memory management is already done for you. Containers shouldn't be ever allocated on the heap. Simply do
wstring strVal;
vector<wstring> vecVal;
map<wstring,wstring> mapVal;
And drop the pointers. C++ containers do all the magic by themselves and are generally small by themselves (sizeof(std::vector) is usually 3*sizeof(void*)).
Assuming you really need testStruct on the heap rather than in automatic storage, you should use a smart pointer:
std::unique_ptr<testStruct> obj = std::make_unique<testStruct>();
There, it's created, allocated on the heap and will be automatically deleted when obj ends its scope. You don't have to worry about deleteing anything anymore.
If you really want to have a function that deletes objects manually, it should look like this:
template <typename T>
void deletePointer(T*& obj)
{
delete obj;
obj = nullptr;
}
It keeps the type of the pointer to be deleted and updates passed pointer with nullptr, so it won't be invalid later on.

Related

What to give a function that expects a raw pointer?

I'm using a library that, in order to construct some object that I use, expects a raw pointer to an object. I'm not sure what it will do with the pointer, to make my code as safe as possible, what should I pass to this function?
Use a unique pointer - if they decide to delete the pointer, I will do a double-delete
Keep track of a raw pointer - bad because I have to remember to write delete, but it could still be a double-delete
Use auto duration and give them a pointer Give them a reference - their code will error if they call delete
Use a shared pointer - same double-delete problem as unique pointer, but now my scope won't hurt their pointer
Based on my reading, option 3 seems like what I should do - they shouldn't be calling delete on the pointer, and this format enforces that. But what if I don't know whether they now or in the future will call delete on the reference I gave them? Use a shared pointer and say "not my fault about the double delete"?
#include <memory>
#include <iostream>
class ComplexObj {
public:
ComplexObj() : m_field(0) {}
ComplexObj(int data) : m_field(data) {}
void print() { std::cout << m_field << std::endl; }
private:
int m_field;
};
class BlackBox {
public:
BlackBox(ComplexObj* data) {
m_field = *data;
// Do other things I guess...
delete data;
std::cout << "Construction complete" << std::endl;
}
void print_data() { m_field.print(); }
private:
ComplexObj m_field;
};
int main(int argc, char* argv[]) {
// Use a smart pointer
std::unique_ptr<ComplexObj> my_ptr(new ComplexObj(1));
BlackBox obj1 = BlackBox(my_ptr.get());
obj1.print_data();
my_ptr->print(); // Bad data, since BlackBox free'd
// double delete when my_ptr goes out of scope
// Manually manage the memory
ComplexObj* manual = new ComplexObj(2);
BlackBox obj2 = BlackBox(manual);
obj2.print_data();
manual->print(); // Bad data, since BlackBox free'd
delete manual; // Pair new and delete, but this is a double delete
// Edit: use auto-duration and give them a pointer
ComplexObj by_ref(3);
BlackBox obj3 = BlackBox(&by_ref); // they can't call delete on the pointer they have
obj3.print_data();
by_ref.print();
// Use a shared pointer
std::shared_ptr<ComplexObj> our_ptr(new ComplexObj(4));
BlackBox obj4 = BlackBox(our_ptr.get());
obj4.print_data();
our_ptr->print(); // Bad data, they have free'd
// double delete when our_ptr goes out of scope
return 0;
}
Other questions I read related to this topic...
unique_ptr.get() is legit at times
I should pass by reference
I think I am case 2 and should pass by reference
You cannot solve this problem with the information you have. All choices produce garbage.
You have to read the documentation of the API you are using.
Doing any of your 4 answers without knowing if they take ownership of the pointer will result problems.
Life sometimes sucks.
If you have a corrupt or hostile API, the only halfway safe thing to do is to interact with it in a separate process, carefully flush all communication, and shut down the process.
If the API isn't corrupt or hostile, you should be able to know if it is taking ownership of the pointed to object. Calling an API without knowing this is a common mistake in novice C++ programmers. Don't do it. Yes, this sucks.
If this API is at all internal and you have any control, seek to make all "owning pointer" arguments be std::unique_ptr<>s. That makes it clear in the API that you intend to own the object and delete it later.

C++ - need help understanding the delete function

I've been having trouble understanding the delete and delete [] functions in C++. Here's what I know so far:
aClass *ptr = new aClass(); //Allocates memory on the heap for a aClass object
//Adds a pointer to that object
...
delete ptr; //ptr is still a pointer, but the object that it
//was pointing to is now destroyed. ptr is
//pointing to memory garbage at this point
ptr = anotehrOjbectPtr //ptr is now pointing to something else
In the case that this happens,
aClass *ptr new aClass();
...
ptr = anotherObjectPtr
the object that pointer was pointing to, is now lost in memory, adn this will cause a memory leak. The object should've been deleted first.
I hope the above is correct
But I wrote this small program, where I'm getting some unexpected behaviour
#include <iostream>
#include <string>
using namespace std;
class Database {
private:
Database() {
arrNames = NULL;
capacity = 1;
size = 0;
}
Database(const Database &db) {}
Database &operator=(const Database &db) {}
string *arrNames;
int capacity, size;
public:
static Database &getDB() {
static Database database;
return database;
}
void addName(string name) {
if (arrNames == NULL) {
arrNames = new string[capacity];
}
if (size == capacity - 1) {
capacity *= 2;
string *temp = new string[capacity];
int i = 0;
while (i <= size) {
temp[i] = arrNames[i];
i++;
}
delete [] arrNames;
arrNames = temp;
}
arrNames[size] = name;
size++;
}
void print() {
int i = 0;
while (i <= size) {
cout << arrNames[i] << endl;
i++;
}
}
};
int main() {
Database &database = Database::getDB();
Database &db = Database::getDB();
Database &info = Database::getDB();
database.addName("Neo");
db.addName("Morpheus");
info.addName("Agent Smith");
database.print();
db.print();
info.print();
}
In the addName function, when I call delete [] arrNames, what I think is happening is that the memory associated with the current array arrNames is destroyed, so arrNames is now pointing at garbage, Then arrNames is directed to point to another location in memory that is pointed to by temp. So if I hadn't called delete [] arrNames, then that location in memory would've been invalid, causing a memory leak. However, when I comment out that line, the code still works without problems. Am I not understanding something here?
Sorry that this si so long
Thanks for the halp
However, when I comment out that line, the code still works without problems. Am I not understanding something here?
An important thing to know about programming is that doing things correctly is not merely a matter of having things apparently work.
Often times you can try something out hand have things appear to work, but then some outside circumstances change, something you're not explicitly controlling or accounting for, and things stop working. For example you might write a program and it runs find on your computer, then you try to demo it to someone and happen to run it on their computer, and the program crashes. This idea is the basis of the running joke among programmers: "It works for me."
So things might appear to work, but in order to know that things will work even when conditions change you have to meet a higher standard.
You've been told how to do things correctly with delete, but that doesn't necessarily mean that things will break in an obvious way if you fail to do so. You need to abandon the idea that you can definitively determine whether something is correct or not by trying it out.
From what I think I see in your code, it looks like addName() is meant to append the new name onto the dynamic array. Doing this yourself can be headache inducing, and there is an existing convenient STL template for just this which I strongly recommend, called vector, from the <vector> header.
If you add #include <vector> and change string *arrNames to vector<string> arrNames, then your entire addName() function can be reduced to:
void addName(string name){
arrNames.push_back(name);
}
From the vector.size() method, you can determine the current length of the vector as well, and your members capacity and size are no longer needed.
A memory leak doesn't involve anything being made invalid. Quite the reverse, it's a failure to make a memory location invalid, causing it to remain in use even when it shouldn't be.
First of all, when you delete something, you are not destroying it in memory, just making it available for some further allocation. This is somewhat similar to filesystem - when you delete file, you just say space it occupied is now available for some new data. You could actually retrieve unmodified data after you called delete on them, but this is undefined behavior and will be compiler/OS specific.
If you don´t delete[] arrNames, you leave its data forgotten in your process´s memory, and creating memory leak. But beside this fatal flaw, there is no more magic happening.

Why does this cause a segfault in C++?

When I try to add an Object pointer to a std::list pointer I get a segfault. Why?
object.h
#ifndef DELETEME_H
#define DELETEME_H
class Object
{
public:
Object(): yes(0) {};
int yes;
};
#endif
object.cpp
#include <list>
#include "deleteme.h"
int main()
{
std::list<Object*> *pList;
Object *pObject;
pObject = new Object();
pList->push_front(pObject);
}
It causes a segfault because pList is not initialized.
std::list<Object*> *pList; // You declared it but you have not said what
// value lives here.
So when you try and use it:
pList->push_front(pObject); // This is undefined behavior.
If you turn your compiler warning on(up) the compiler will warn you this is a problem. You should really tell your compiler to treat all warnings as errors.
How do you solve it.
You should create a list.
std::list<Object*> *pList = new std::list<Object*>;
But creating it as a pointer is a bad idea (no a very bad idea). You have just opened up a hole can of worms that you don't want to handle. You should never (read hardly ever (or just never)) dynamically create memory. It leads to all sorts of problems with exceptions and leaks. Until you understand ownership semantics stick to objects.
std::list<Object> pList;
pList.push_back(Object());
In the comments you are worried about returning it from a function.
std::list<Object> getList()
{
std::list<Object> result;
result.push_back(Object());
result.push_back(Object());
return result;
}
int main()
{
// Technically this copies the list out of the function
// when the return is called (so your object and the list)
// must be copyable.
std::list<Object> data = getList();
// But in reality it will not be copied.
// Because the copiler will invoke NRVO and build it in place
// at the destination. If you put print statements in your objects
// constructor/destructor etc.. you can try and spot the copies.
// Turn on optimizations and any copies that did exist will be
// removed.
}

Managing objects returned from C++ function

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;
}

Deleting pointers that were allocated in another shared library

UPDATE (SOLVED): All right, I'm a complete idiot! Turns out in the "do stuff with data" part in my main program I ended up incrementing the pointer, so the delete obviously wouldn't work! D'oh!
So I am compiling a shared library that has a function similar to this (super simplified view), and this library is also mine- so I know how data is allocated:
// inside library
void* getData(int size) { // with other parameters
UINT8* data = new UINT8[size]; // where typedef uint8_t UINT8; for gcc
// do a socket read, where data is the buffer
blockingRead (someSocket, data, propertySize);
return (void*) data;
}
It has to return a void pointer, as the data could be a struct (so one can just cast to the struct).
The problem is, I am using this pointer in my main program, and I want to delete it when I'm done. If I do this in my main program:
// inside main program
char* data = (char*) Library::getData(5);
// do stuff with data
delete[] data; // crashes with:
// *** glibc detected *** core: free(): invalid pointer: 0x00002aaab007bca4 ***
I thought maybe I should delete it in the shared library instead:
// inside library
void disposeData(void* data) { // call this from main program
delete[] (UINT8*) data; // cast it back to the original type of pointer
}
But I still get the same crash! Everything works fine and dandy if I don't delete, but I don't want unnecessary memory leaks all over my program.
I'm probably doing something dumb somewhere- please help me find the error in my ways!
EDIT: As pointed out in the comments, it seems that the above code works- I will have to see what specifically causes the errors in my code.
Have you tried using valgrind? Using valgrind will help you pinpoint a wide range of memory management errors, which are the likely cause of the problem. The error you are seeing looks either like heap corruption (as #nos says, probably in the do stuff part), or that you are not in fact freeing the same object you originally allocated.
If the library is providing you with allocated pointers, it should explain how to deallocate them. It may provide its own function for deallocation. Unless you have the source code to the library and can verify that it is using new[] to create the pointer, you can't be sure how it is allocating memory. Your crash is likely because your deallocator doesn't match its allocator.
How about using a more RAII based design such as smart pointers instead? Boost smart pointers are quite well designed.
I bet you're doing something like that, as you mention "casts":
#include <stdio.h>
class B { int x; };
class C { int y; };
class A : public B, public C { };
void* getData()
{
A* a = new A();
printf("%p\n", a);
C* c = a;
printf("%p\n", c);
return c;
}
void deleteData(void* x)
{
// delete (A*)x; // incorrect; causes crash
delete (A*)(C*)x; // correct
}
int main()
{
void* x = getData();
deleteData(x);
return 0;
}
Beware, the compiler may be translating what looks like an innocent cast into pointer arithmetic behind your back.