简体   繁体   中英

Deleting what wasn't allocated with new using pointers

Update: Please Note, I am forced to return a pointer to the result since I need to support multiple operations in one line (will be used in python)

Today, I have faced the hardest problem in my programming career Ever, So I hope someone can help.

In graph_p.h I have:

typedef struct Graph* Graph_P;

(Graph_P is a pointer for a Graph)

While Graph Is another class which I defined

In graph_p.cpp I have the following functions:

Graph_P create()
{
    try {
        Graph_P graph=new Graph;
        return graph;
    }
    catch (std::bad_alloc &) {
        std::cout << "Error: Allocation Failed" << std::endl;
        return nullptr;
    }
}

void destroy(Graph_P graph_p)
{
    delete graph_p;
}

And the following graphUnion function (which is our topic ):

Graph_P graphUnion(Graph_P graph_in1, Graph_P graph_in2, Graph_P graph_out) {
    try {
        *graph_out=(*graph_in1)+(*graph_in2);
//I have defined operator + between two graphs which returns a new graph built using default c'tor **not using new**

        destroy(graph_out);
        return graph_out;
    }
    catch (CException::exception &e) {
        std::cout << e.what() << std::endl;
        return nullptr;
    }
}

What's the problem?

In case operator + failed I'm deleting the content of graph_out which shouldn't be done.

Suggested Solution:

Saving graph_out content in a temporary Graph_P object like this:

Graph_P graphUnion(Graph_P graph_in1, Graph_P graph_in2, Graph_P graph_out) {
    try {
        Graph tmp=*graph_out;
        tmp=(*graph_in1)+(*graph_in2);
        destroy(graph_out);
        graph_out=&tmp;
        return graph_out;
    }
    catch (CException::exception &e) {
        std::cout << e.what() << std::endl;
        return nullptr;
    }
} 

What's the problem?

I am putting a value inside graph_out that wasn't allocated via new so if the user types destroy(graph_out) outside the function, that would be an undefined action since I read:

You need to delete only what you new ed

How may I fix this?

typedef struct Graph* Graph_P;

This is a bad idea. Obfuscating pointer like this should be avoided.


Problem is here:

Graph tmp=*graph_out;
// ...
graph_out=&tmp;
return graph_out;

You create a graph that local to the function. It is automatically destroyed when the function returns. You return a pointer to that graph. The returned pointer will be invalid outside of the function. Attempting to delete or access the non-existing value through that dangling pointer results in undefined behaviour.

I think the simplest solution would be to add if statement in destroy() function to make sure that graph_p isn't a nullptr:

void destroy(Graph_P graph_p)
{
    if (graph_p != nullptr) {
        delete graph_p;
    }
}

I think it would be a good idea to make Graph_P a smart pointer (if you're using at least C++11) - memory allocation would be easier.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM