1

I have some problem with c++ pointer.

Here is my code:

#include <iostream>
#include <vector>

int main() {
    std::vector<int*> * data = new std::vector<int*>;

    for (int i = 0; i < 1000; i++) {
        data->push_back(new int[100000]);
    }

    for (int i = 0; i < 100; i++) {
        delete data->at(i);
    }

    data->clear();
    delete data;
    data = nullptr;
    return 0;
}

After

std::vector<int*> * data = new std::vector<int*>;
for (int i = 0; i < 1000; i++) {
    data->push_back(new int[100000]);
}

It takes 384Mb (I found it in task manager)

But after

for (int i = 0; i < 100; i++) {
    delete data->at(i);
}

It still takes 346Mb

After

delete data;
data = nullptr;

It doesn't change anything

My problem is, what can I do to completely delete a pointer and free memory?

letsintegreat
  • 3,328
  • 4
  • 18
  • 39
The bottle
  • 11
  • 3
  • 7
    You're pushing `1000` times and deleting `100` times, is that deliberate? – Azeem Feb 17 '19 at 05:40
  • 7
    Task manager is not a way to detect memory leaks. Also, most memory managers will not release memory back to the OS immediately when it is freed, because they presume you will use it again. – Ken White Feb 17 '19 at 05:40
  • 3
    `new[]` should be balanced by `delete[]`. Also, you almost should never be using `new[]` and `delete[]` anyway. – jamesdlin Feb 17 '19 at 05:41
  • You can try calling [shrink_to_fit](https://en.cppreference.com/w/cpp/container/vector/shrink_to_fit) and see if that helps. – Ted Lyngmo Feb 17 '19 at 05:45
  • You are misunderstanding what delete does. It allows your program to use the memory again, it does not allow other programs to use the memory again. So the Task manager still shows your program as having the memory. – john Feb 17 '19 at 07:51

1 Answers1

0

First, you probably aren't actually deleting everything. You loop only goes to 100, and you're pushing on 1000 items. Secondly, your use of data->clear() is largely pointless and irrelevant. Vectors frequently do not ever shrink themselves no matter what you do. And even if they do, you're just deleting it anyway.

Lastly, don't use new and delete, and use raw pointers sparingly. If you hadn't used them in the first place, you wouldn't have made the mistakes you did. You should've done this:

#include <iostream>
#include <vector>
#include <memory>

int main() {
    using ::std::make_unique;
    using ::std::unique_ptr;
    typedef unique_ptr<int []> ary_el_t;
    auto data = make_unique<::std::vector<ary_el_t>>();

    for (int i = 0; i < 1000; i++)
    {
        data->push_back(make_unique<int[]>(100000));
    }

    data.reset();

    return 0;
}

And, even if you did, you might still not get the memory back. Allocators will reuse freed space when asked for more space, but they often don't return it to the operating system.

The above code does require C++14 to work. But recent versions of Visual Studio should support that. I tested this with g++ on my Linux box, and my allocator does return memory to the OS, so I was able to verify that indeed, all the de-allocation works.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
  • Yes you are right, `data.reset();` is correct. Perception is sometimes a strange thing. Even tough I wrote `data->reset` i thought it was `clear`. – t.niese Feb 17 '19 at 09:20
  • Writing `use raw pointers sparingly` is also not necessarily right. Use smart pointers when you want to keep or transfer ownership, and references or raw pointers if you just want to just pass an object for the current usage. So for most utility function to which you pass an object you won't pass that by a smart pointer, but by its raw pointer or reference. – t.niese Feb 17 '19 at 09:25