简体   繁体   English

我可以强制std :: vector留下内存泄漏吗?

[英]Can I force std::vector to leave a memory leak?

Can I force std::vector to not deallocate its memory after the vector goes out of scope? 在向量超出范围后,我可以强制std :: vector不释放其内存吗?

For example, if I have 例如,如果我有

int* foo() {
    std::vector<int> v(10,1); // trivial vector
    return &v[0];
}

int main()
{
    int* bar = foo();
    std::cout << bar[5] << std::endl;
}

There is no guarantee that the values will still be accessible here. 无法保证此处仍可访问这些值。

I am currently simply doing this 我目前只是这样做

int* foo() {
  std::vector<int> v(10,1);
  int* w = new int[10];
  for (int i=0; i<10; i++) {
    w[i] = v[i];
  }
  return w;
}

but it is a little wasteful to repopulate a whole new array. 但重新填充一个全新的阵列有点浪费。 Is there a way to force std::vector to not delete its array? 有没有办法强制std :: vector不删除它的数组?

Note: I am not returning the vector itself because I am interfacing c++ with python using SWIG, and ARG_OUTVIEW_ARRAY requires a raw pointer and, in fact, an intentional memory leak. 注意:我没有返回向量本身,因为我使用SWIG连接c ++和python,而ARG_OUTVIEW_ARRAY需要一个原始指针,实际上是故意的内存泄漏。 I would still however like to be able to make use of vector features while constructing the data itself. 但是,我仍然希望能够在构建数据本身时使用矢量要素。

It is possible but you should never do it. 这是可能的,但你永远不应该这样做。 Forcing a vector to leave memory leak is a terrible idea and if you need such a thing then you need to re-think your design. 强制矢量留下内存泄漏是一个可怕的想法,如果你需要这样的东西,那么你需要重新思考你的设计。 std::vector is a resource managing type whose one of the main goals is to ensure that we don't have a leak. std :: vector是一种资源管理类型,其主要目标之一是确保我们没有泄漏。 Never try to break that. 永远不要试图打破这一点。

Now, to answer your specific question: std::vector takes an allocator type as second template parameter which is default to std::allocator<T> . 现在,回答您的具体问题: std::vector将分配器类型作为第二个模板参数,默认为std::allocator<T> Now you can write a custom allocator that doesn't release any memory and use that with your vector. 现在,您可以编写一个不释放任何内存的自定义分配器,并将其与向量一起使用。 Writing a custom allocator is not very trivial work, so I'm not going to describe that here (but you can Google to find the tutorials). 编写自定义分配器并不是一件非常简单的工作,因此我不打算在此描述(但您可以通过Google查找教程)。

If you really want to use custom allocator then you must ensure that your vector never triggers a grow operation. 如果您确实想使用自定义分配器,则必须确保向量永远不会触发增长操作。 Cause during growing capacity the vector will move/copy data to new location and release the old memories using the allocator. 在增长能力期间,矢量将移动/复制数据到新位置并使用分配器释放旧存储器。 If you use an allocator that leaks then during growing you not only retain the final data, but also retain the old memories which I'm sure that you don't want to retain. 如果你使用一个在发展过程中泄漏的分配器,你不仅会保留最终数据,还会保留我确定你不想保留的旧记忆。 So make sure that you create the vector with full capacity. 因此,请确保创建具有完整容量的向量。

No. 没有。

Vectors are not implemented to have memory leaks, and the interface does not provide a way to create one. 未实现向量以使内存泄漏,并且接口不提供创建内存的方法。

You can't "steal" the memory (removing ownership of it from the vector), which is possibly a bit of a shame. 你不能“偷”的内存(从载体去除它的所有权),这可能一个有点羞耻的。

Sorry, but you are going to have to either copy (as you're doing now), or not use vector. 对不起,但是您必须要么复制(正如您现在所做的那样),要么不使用向量。

The vector is desiged to prevent leaks. 设计vector以防止泄漏。

But if you want to shoot yourself in the foot, it's possible. 但如果你想用脚射击自己,这是可能的。 Here's how you prevent the vector from deallocating its internal array: 以下是阻止向量释放其内部数组的方法:

int *foo()
{
    std::vector<int> v(10,1);

    int *ret = v.data();
    new (&v) std::vector<int>; // Replace `v` with an empty vector. Old storage is leaked.
    return ret;
}

As the other answers say, you should never do it. 正如其他答案所说,你永远不应该这样做。

This is a bad idea, but possible by creating a custom allocator that does not deallocate as said in other answers. 这是一个坏主意,但可以通过创建一个不会像其他答案中所述那样解除分配的自定义分配器来实现。

For example : (boilerplate mostly from cppref ) 例如:(样板主要来自cppref

#include <cstdlib>
#include <new>
#include <vector>

template <typename T>
struct LeakingAllocator 
{
  using value_type = T;
  LeakingAllocator() = default;

  template <typename U> constexpr LeakingAllocator(const LeakingAllocator<U>&) noexcept {}

  T* allocate(std::size_t n) 
  {
    if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc(); // check for overflow

    if(auto p = static_cast<T*>(std::malloc(n*sizeof(T)))) return p; // return p if malloc returns a valid object
    throw std::bad_alloc(); // otherwise just throw.
  }

  void deallocate(T* p, std::size_t) noexcept { /*leak intentionally*/ }
};


template <typename T, typename U>
bool operator==(const LeakingAllocator<T>&, const LeakingAllocator<U>&) { return true; }
template <typename T, typename U>
bool operator!=(const LeakingAllocator<T>&, const LeakingAllocator<U>&) { return false; }

template <typename T>
using LeakingVector = std::vector<T, LeakingAllocator<T>>;

Then code like 那么代码就像

int* ret()
{
    LeakingVector<int> a;
    a.resize(10);
    return &a[0];
}

int main()
{
    auto ptr = ret();
    *ptr = 10;
    std::cout << *ptr;
}

becomes valid. 变得有效。

Not sure but, yes. 不确定但是,是的。

You can create a custum allocator who do nothing when deallocate => leak 您可以创建一个在deallocate => leak时不执行任何操作的custum 分配器

Or may be you can jsut create your vector on the heap so it will leak anyway. 或者也许你可以在堆上创建你的vector ,所以它无论如何都会泄漏。

int* foo() {
    std::vector<int>* v = new std::vector<int>(10,1); 
    return &((*v)[0]);
    // no delete
}

int main()
{
    int* bar = foo();
    std::cout << bar[5] << std::endl;
}

No. 没有。

And you're doing it wrong. 而你做错了。 Return the vector instead so the lifetime works out: 返回向量,以便生命周期成功:

Write your own special Python memory vector class , something like (most crudely): 编写自己特殊的Python内存向量class ,类似于(最粗略地):

template <typename T>
class python_vector
{
    T* buffer_;
public:
    python_vector(size_t n, const T& value) : buffer_{new T(n)}
    {}
    // copy, assignment, operator[](), *etc*
    ~python_vector()
    {
        // DO NOTHING!
    }
}

python_vector<int> foo() {      
    python_vector<int> v(10,1);
    // process v
    return v;
}

int main()
{
    python_vector<int> bar = foo();  // copy allusion will build only one python_vector here
    std::cout << bar[5] << std::endl;
}

In C++ you would most probably write: 在C ++中你最有可能写:

auto foo()
{
    std::vector<int> v(10,1); // trivial vector
    return v;
}

int main()
{
    const auto bar = foo();
    std::cout << bar[5] << std::endl;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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