0

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.

Clonkex
  • 3,373
  • 7
  • 38
  • 55
  • I say let the person who allocates memory for it delete it. – chris Apr 17 '13 at 03:12
  • Think of it in terms of ownership. The person who allocates the object owns it. The person who owns it is responsible for deleting it. – Captain Obvlious Apr 17 '13 at 03:18
  • What do you mean by person? – Clonkex Apr 17 '13 at 03:19
  • @Clonkex, I mean the function really. If you write a function to allocate memory, do something with it, and return it, make the user allocate it, pass it in, and then modify that. There are no surprises for the user then. Of course, depending on the type of memory you need, there's probably a better RAII alternative. – chris Apr 17 '13 at 03:21
  • 1
    Use smart pointers such as `shared_ptr`, `unique_ptr` to track it for you. – Keith Apr 17 '13 at 03:22
  • @Keith I don't really understand smart pointers and I certainly don't know how to use them. -chris I have no idea what you mean by all that; assume I know very little about pointers. Also I have no idea what RAII is. – Clonkex Apr 17 '13 at 03:27
  • @Clonkex See for example http://en.wikipedia.org/wiki/Smart_pointer . Smart pointers are there to simplify managing allocated memory over using raw pointers. – Keith Apr 17 '13 at 03:55
  • I'm curious... what kind of *horrible* design do you have that requires you to be able to call delete on random pointers (which may be either unallocated and pointing to junk, or already deleted and pointing to junk)? It sounds to me like you're looking to solve the **WRONG** thing: the symptom, instead of the problem. – Nik Bougalis Apr 17 '13 at 05:14
  • @Nik It's really not as horrible as it sounds. It's a very simple design and I'm trying to minimise my code as much as possible. I'm effectively saying, "If MeshData Exists Then Delete MeshData". That's all. MeshData **must** be a pointer because its class has no default ctor and overloads and protects the `=` operator. The design of my code is easy to debug, easy to read and shouldn't need debugging because it's so simple. But it wasn't nice of you to call my design _horrible_ anyway. That kind of statement is very unhelpful. It will work perfectly and it's mine so I may design it how I like. – Clonkex Apr 17 '13 at 05:51
  • @Clonkex: I suggest you learn what RAII and smart pointers are all about. They are *much* simpler than messing around trying to manage memory by steam using `new` and `delete` - that becomes almost impossible if you need to deal with exceptions. Using them, you won't get into this kind of dysfunctional situation in the first place. – Mike Seymour Apr 17 '13 at 06:16
  • @Mike I shall take your advice...next time. For now, it would be far too complicated to learn a whole new thing just for a project as simple as mine :) But I definitely will learn to use smart pointers and RAII. I'll never rise through the ranks of awesome programmers if I don't. I hope to one day (soon, even, if my project goes well) generate all my income by my programming-from-home. Or maybe I'll move to America and work for Valve ;) Thanks for convincing me I need to learn those things :) – Clonkex Apr 17 '13 at 10:29
  • @Clonkex your design may seem elegant to you, but you will forgive me for saying that it doesn't seem elegant to me. But if it will make you feel better, I will rephrase: Any design that requires the ability to call `delete` on pointers which may be uninitialized or which have already been deleted requires rethinking. – Nik Bougalis Apr 17 '13 at 15:16
  • @Nik Not yet it doesn't. I didn't say it was elegant; far from it. I just said it was _simple_. The pointers are only ever given data to point to in 1 place, and `deleteMeshData()` is always called 1 line before to make sure that the mesh data doesn't already exist. There's nothing complicated about it and absolutely no reason to redesign atm. Any redesign requires quite literally 10 times as much code to achieve exactly the same thing, without any benefits (in my situation; of course there's benefits to RAII in bigger projects). **I will not rewrite my code** for this project :) – Clonkex Apr 18 '13 at 00:29

4 Answers4

4

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.

stardust
  • 5,918
  • 1
  • 18
  • 20
  • It doesn't cover `int i; int* thingy = &i;` – Jesse Good Apr 17 '13 at 03:13
  • @JesseGood in that case he would have to use some kind of smart pointer policy I guess. – stardust Apr 17 '13 at 03:15
  • @Jesse I never need to do `int i; int* thingy = &i;`. – Clonkex Apr 17 '13 at 03:20
  • @JesseGood IMHO you're cavilling )) I think OP got a full answer to question (s)he raised – borisbn Apr 17 '13 at 03:21
  • @user2280716 What happens _after_ I've deleted it? I forgot to mention that I need to be able to `delete` as many times as I like without the pointer necessarily containing data. I think I'll have to re-write my code if it's this difficult... – Clonkex Apr 17 '13 at 03:22
  • @borisbn: Maybe, but why manually call `delete` when you can do `std::unique_ptr p(new int);`? – Jesse Good Apr 17 '13 at 03:24
  • @Jesse Woh, what the heck is `std::unique_ptr p(new int);`?? That should be explained in a full answer. – Clonkex Apr 17 '13 at 03:26
  • @user2280716 You might want to also set `thingy` to `NULL` after deleting it. – Code-Apprentice Apr 17 '13 at 03:28
  • Ah now THAT would work. Thanks, Code-Guru @user2280716, if you edit your answer to include that I'll mark it as the accepted answer :) – Clonkex Apr 17 '13 at 03:31
  • @Code-Guru If I used `delete thingy; thingy=NULL;` would it still be valid to use `delete` on it after that, given I didn't use `new` to begin with? – Clonkex Apr 17 '13 at 03:33
  • @Clonkex Yes. Deleting a NULL pointer is legal and perfectly safe. – Code-Apprentice Apr 17 '13 at 03:36
  • @Clonkex: `delete`ing a `NULL` pointer is perfectly valid. It is defined as No-Op. – Alok Save Apr 17 '13 at 03:36
  • Just to be clear- AFTER that NULL pointer has been deleted, the pointer no longer points to anything and would have to be assigned NULL or some data to make it safe to `delete` again, right? – Clonkex Apr 17 '13 at 03:40
  • 1
    I was gone for 5 min wth happened here? – stardust Apr 17 '13 at 03:42
  • @Clonkex You can delete it as many times as you want. As long as it is NULL. – stardust Apr 17 '13 at 03:43
  • @user2280716 So...`delete` must only vaporise the data pointed to be the pointer but not change the pointer...? Or does it only not change the pointer if the pointer is NULL? I just want to get this straight in my head so I actually understand what I'm doing ;) – Clonkex Apr 17 '13 at 03:46
  • @Clonkex delete **doesn't change the value of the pointer**. It just tells the OS that the memory pointed to is not used anymore. You need to assign it to NULL after delete just in case you delete it again by mistake. Which is really not disastrous but just meaningless. – stardust Apr 17 '13 at 03:56
  • Theoretically, deleting an already-deleted pointer (one that has not been assigned NULL) _could_ (but doesn't necessarily) delete stuff that it's not meant to, stuff that is still in use, right? Thanks for taking the time to answer my repeated questions :) – Clonkex Apr 17 '13 at 04:33
  • @Clonkex No worries man. Not a problem. I think this has more detailed explanation of what is good practice and what not. http://stackoverflow.com/questions/1931126/is-it-good-practice-to-null-a-pointer-after-deleting-it – stardust Apr 17 '13 at 04:36
  • @Clonkex They over complicate things a bit. But I think you can filter out the unnecessary explanation. – stardust Apr 17 '13 at 04:37
  • 1
    Just looking at this comment chain from 6 years ago. Geez, I don't know why I had such a hard time understanding what you were saying. It's so simple. I guess this is why it's hard to teach programming to beginners, because they don't _get_ simple things :P – Clonkex Sep 11 '19 at 23:15
  • 1
    @Clonkex :) That's good to hear. If it sounds so basic now then this whole comment chain was all worth it. – stardust Sep 30 '19 at 09:02
2

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;
bames53
  • 86,085
  • 15
  • 179
  • 244
0

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.

harper
  • 13,345
  • 8
  • 56
  • 105
  • I don't need to be able to identify what the pointer points to, just whether it points to any data at all. The answer I accepted answers this for me perfectly :) Thanks for the additional info, though :) – Clonkex Apr 17 '13 at 04:35
0

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();
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Woh, no thanks! Far too complicated! I just needed something simple and the accepted answer does this perfectly :) Thanks for the additional information, though :) – Clonkex Apr 17 '13 at 05:04
  • @Clonkex the accepted answer appears simple, but using that method correctly in practice is in fact very difficult. For example such code is pretty much guaranteed to be exception unsafe. Using RAII with well-defined ownership policies is much easier to get right in practice. – bames53 Apr 17 '13 at 17:59
  • @bames53 I fully intend to learn to use RAII and/or smart pointers for my next project, but right now I have no need for exceptions or anything else that sophisticated. I'm primarily a BASIC programmer (DBPro), so I naturally try to make everything behave like in BASIC. I realise this is bad practice so I'm slowly learning to write proper OO code that takes advantage of such advanced features as templates and now smart pointers/RAII. I'm getting there. – Clonkex Apr 18 '13 at 00:23