How to test if destructor cleaned memory

hello,

I am writing simple handle that stores reference to object in free store. I want to write test to check if after destructor invocation this object is actually cleaned. Currently I see that the pointer points to the same object, as I understand it is not mandatory that memory will be errased.

There are few suggestions in the web to introduce some bool flag to test if destructor was called, but this does not actually guarantee that object was deleted.

Is there a way to test actual deletion?

If I try to get value from the object after it was deleted I got SIGABRT. Is it possible to catch it, so i can assert on it( in boost test)
Last edited on
I don't follow. How are you going to test anything about the object after the destructor returned? If the destructor returned then the object no longer exists, so what could you possibly write in your test if you can't access anything in an object that no longer exists?

Suggestion: Why not just use an std::unique_ptr to store the pointer so you can obviate the need to test resource management?
The reason to not use unique_ptr is because I am writing program that might be used on platforms that do not have standard library (e.g. arduino).

I want to test that memory is freed. "How to do it?" is my question
Arduino isn't programmed in C++, though. It's a custom language that's very similar, but different.

I want to test that memory is freed. "How to do it?" is my question
If that's all the information you're going to give, then my answer is "you can't". Once the destructor has returned either the memory is freed or the pointer is leaked. You can't know which.
There are plenty of memory leak detectors like this one:

https://marketplace.visualstudio.com/items?itemName=ArkadyShapkin.VisualLeakDetectorforVisualC


While it won't tell you which variables have leaked or not, you can theoretically figure it out through the blocks of memory that it tells you have leaked.


You could also keep track of sizes. Output the total size of the memory you want to free, and then output the size of exactly what is being freed. If they're equivalent, you've most likely freed all the memory.
Is there a way to test actual deletion?

What does that mean? Can you explain what you mean without using the word "delete"?

it is not mandatory that memory will be errased.

What does that mean? Memory cannot be "erased". All that can happen is that some numbers in memory can change.

What are you worried is not happening? What bad thing will happen if this is somehow going wrong?
Last edited on
Use (and test for) nullptr.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
using namespace std;

void testAllocated( int *p )
{
   cout << "Pointer is " << ( p ? "allocated" : "not allocated" ) << '\n';
}


void constructor( int * &p )           // simulated constructor
{
   p = new int;
}


void destructor( int * &p )            // simulated destructor
{
   delete p;
   p = nullptr;
}


int main()
{
   int *p = nullptr;
   testAllocated( p );

   constructor( p );
   testAllocated( p );

   destructor( p );
   testAllocated( p );
}


Pointer is not allocated
Pointer is allocated
Pointer is not allocated
Last edited on
lastchance, if you remove line 18, your test still will be green.

This what I want to test, the fact of deletion, explicitly, if possible.
This is not a simple task. You would need to somehow hook in your own code into the underlying library calls from new/delete/malloc/free and add your own handlers to track data. I believe programs like Valgrind can do this, specifically its "memcheck" functionality, but I have no idea what would be needed for arduino.

As the other have mentioned, memory leak detectors exist; I assume something like this exists for arduino.

I don't really see what the specific issue is. It sounds like you know that delete is being called, but you simply don't trust what that function is doing? If you think your compiler has an error, then I would take it up with arduino devs. Trying to use a deleted object is undefined behavior. You're lucky that you get a SIGABRT.
Last edited on
afedorov wrote:
lastchance, if you remove line 18, your test still will be green.


Pardon?
fedorov is saying that checking for nullptr is not a guarantee that delete was called, because something else could have set it to be a nullptr without actually freeing the memory (imagine the destructor as being a black box).

Which goes back to the suggestions of using a memory leak detector. But I don't know of a handy detector for embedded devices. Found this with a search: https://github.com/DevLaTron/ArduinoProfiler but I think it just shows memory usage.

or...
https://forum.arduino.cc/index.php?topic=40031.0
simon monk wrote:
The best way to avoid memory leaks is to never allocate anything dynamically. Its a rare situation that justifies it on a little device like the Arduino. Careful design and statically allocated buffers can usually avoid it.
Last edited on
Ok, let me clarify few things.

I have a Java background. In my java projects I always use TDD. I am writing memory handle and want to write test, that it is indeed cleans the memory.

I am writing a generic library, and do not want to couple it to std as of now. Is it good or bad is out of discussion right now. I am setting up hypothetical situation where I cannot couple to std library, Arduino was only brought as an example of platform that does not have std(regardless of if their C++ is actually C++ or not).

The only think I am trying to understand if it is possible to write simple unit test that checks invocation of delete function on a give pointer in my handle, so if someone removes line 18 in lastchance's code there will be big red test.

As I understand it is not possible as this functionality is low level.

I'm curious, how are you testing that memory is being freed in Java, a language which doesn't even have manual memory management?

Memory management doesn't really have to do with the standard library; the language itself provides new/delete. You can't really test new/delete itself without an external tool like Valgrind or equivalent. There might be compiler extensions which allow for more memory debugging, but I'm not familiar with them, so maybe someone else knows.
Last edited on
I am writing a generic library, and do not want to couple it to std as of now. Is it good or bad is out of discussion right now. I am setting up hypothetical situation where I cannot couple to std library, Arduino was only brought as an example of platform that does not have std(regardless of if their C++ is actually C++ or not).
If this is the entire problem then the solution is simple: copy the unique_ptr implementation into your project. The class should be a thousand lines at the most.

If it was possible to test if memory was correctly released after a specific point in execution then it would be possible to write a general function that always correctly releases any memory leaks.
In C++, the solution to the problem of correctly managing memory is not "test that you're doing it", it's "don't manage memory manually; use RAII".

EDIT: Or hell, just write a simple wrapper class. Most resource management helper classes are as simple as
1
2
3
4
5
6
7
8
9
10
11
class HandleWrapper{
    HANDLE h;
public:
    HandleWrapper(HANDLE);
    HandleWrapper(const HandleWrapper &) = delete;
    HandleWrapper(HandleWrapper &&) = delete;
    HandleWrapper &operator=(const HandleWrapper &) = delete;
    HandleWrapper &operator=(HandleWrapper &&) = delete;
    ~HandleWrapper();
    HANDLE get() const;
};
Last edited on
I have not done this, and I firmly believe you are asking either the wrong question or have some idea in mind that is not productive, but, taking it at face value...

I *think* you can *probably* find out who owns a section of memory if you make your program as if it were a debugger (there are ways to do that, it lets you peek at memory you do not own to see if something else is screwing it up) and it should tell you what process owns that memory which, if deleted, should be 'not your process'.
This seems like not something one would DO in normal code, though.

And it will not work in any number of scenarious, including you delete it in thread a and ask for memory in thread b, get the same memory back as before, and now you still own it but it was also deleted and returned to the os and then handed back to you.... this is one of several ways attempting such a thing will go sour.
Last edited on
You could also make use of replaceable allocation functions to provide whatever debugging functionality you want.

But the last time we talked about this we discussed implementing unique_ptr or a simpler version of it, and we didn't get anywhere. This is substantially more involved.
Last edited on
afedorov wrote:
The only think I am trying to understand if it is possible to write simple unit test that checks invocation of delete function on a give pointer in my handle

Setting aside that in C++ you aren't meant to call new/delete directly (and if you for some misconstrued reason won't use "std", write your own unique_ptr equivalent), you can in fact do this test yourself with a bit of extra work: you would have to replace the relevant "delete function" (there are more than one, for different situations, see https://en.cppreference.com/w/cpp/memory/new/operator_delete ).
Rough poc:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <cstdio>
#include <cstdlib>

bool testing = false;
void* ptr_to_test; // global! hope your unit tests are single-threaded
void test_on_for(void* p) {
    ptr_to_test = p;
    testing = true;
}
void test_off() { testing = false; }

void operator delete(void* p) noexcept
{
    if (testing && p == ptr_to_test) {
      std::puts("expected delete");
      ptr_to_test = nullptr; // don't expect to call it again!
    } else if (testing)
      std::printf("unexpected delete for pointer %p\n", p);
    std::free(p);
}

int main() {
     int* p1 = new int;
     test_on_for(p1);
     delete p1; // prints "expected delete"
     test_off();
}

Last edited on
Nice, this is probably what I need. Thanks
ja, I've got no output running it through valgrind
Topic archived. No new replies allowed.