簡體   English   中英

我可以強制std :: vector留下內存泄漏嗎?

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

在向量超出范圍后,我可以強制std :: vector不釋放其內存嗎?

例如,如果我有

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

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

無法保證此處仍可訪問這些值。

我目前只是這樣做

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;
}

但重新填充一個全新的陣列有點浪費。 有沒有辦法強制std :: vector不刪除它的數組?

注意:我沒有返回向量本身,因為我使用SWIG連接c ++和python,而ARG_OUTVIEW_ARRAY需要一個原始指針,實際上是故意的內存泄漏。 但是,我仍然希望能夠在構建數據本身時使用矢量要素。

這是可能的,但你永遠不應該這樣做。 強制矢量留下內存泄漏是一個可怕的想法,如果你需要這樣的東西,那么你需要重新思考你的設計。 std :: vector是一種資源管理類型,其主要目標之一是確保我們沒有泄漏。 永遠不要試圖打破這一點。

現在,回答您的具體問題: std::vector將分配器類型作為第二個模板參數,默認為std::allocator<T> 現在,您可以編寫一個不釋放任何內存的自定義分配器,並將其與向量一起使用。 編寫自定義分配器並不是一件非常簡單的工作,因此我不打算在此描述(但您可以通過Google查找教程)。

如果您確實想使用自定義分配器,則必須確保向量永遠不會觸發增長操作。 在增長能力期間,矢量將移動/復制數據到新位置並使用分配器釋放舊存儲器。 如果你使用一個在發展過程中泄漏的分配器,你不僅會保留最終數據,還會保留我確定你不想保留的舊記憶。 因此,請確保創建具有完整容量的向量。

沒有。

未實現向量以使內存泄漏,並且接口不提供創建內存的方法。

你不能“偷”的內存(從載體去除它的所有權),這可能一個有點羞恥的。

對不起,但是您必須要么復制(正如您現在所做的那樣),要么不使用向量。

設計vector以防止泄漏。

但如果你想用腳射擊自己,這是可能的。 以下是阻止向量釋放其內部數組的方法:

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;
}

正如其他答案所說,你永遠不應該這樣做。

這是一個壞主意,但可以通過創建一個不會像其他答案中所述那樣解除分配的自定義分配器來實現。

例如:(樣板主要來自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>>;

那么代碼就像

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

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

變得有效。

不確定但是,是的。

您可以創建一個在deallocate => leak時不執行任何操作的custum 分配器

或者也許你可以在堆上創建你的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;
}

沒有。

而你做錯了。 返回向量,以便生命周期成功:

編寫自己特殊的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;
}

在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