无法从自制矢量中删除元素

问题描述 投票:0回答:1

我的任务是做一个简化版本的 std::vector。我的程序正在服务器上进行测试,无法通过“test resize(with valgrind)”。这是我的向量的实现:

my_vector_impl.h

#include "my_vector.h"
#include <type_traits>
#include <algorithm>
#include <stdexcept>
#include <cmath>

namespace containers {

    template <typename T>
    my_vector<T>::my_vector() {
        capacity_ = 1;
        size_ = 0;
        array_ = reinterpret_cast<T*>(::operator new (sizeof(T)));
    }

    template <typename T>
    my_vector<T>::my_vector(std::size_t n) {
        if (!std::is_default_constructible<T>::value) {
            throw std::runtime_error("Cannot use non default constructible type!");
        }
        capacity_ = (size_t)pow(2, ceil(log2(n)));  // minimum power of two
        size_ = n;
        array_ = reinterpret_cast<T*>(::operator new (sizeof(T) * capacity_));

        for (size_t i = 0; i < size_; i++) {
            new (array_ + i) T();
        }
    }

    template <typename T>
    my_vector<T>::~my_vector() {
        for (size_t i = 0; i < size_; i++) {
            array_[size_ - i - 1].~T();
        }
        ::operator delete(array_);
    }

    template <typename T>
    void my_vector<T>::resize(std::size_t n) {
        if (!std::is_default_constructible<T>::value) {
            throw std::runtime_error("Cannot use non default constructible type!");
        }
        if (n <= size_) {
            for (size_t i = size_ - 1; i > n - 1; i--) {
                array_[i].~T();
            }
            size_ = n;
        }
        else if (n > size_ && n <= capacity_) {
            for (size_t i = size_; i < n; i++) {
                new (array_ + i) T();
            }
            size_ = n;
        }
        else if (n > size_ && n > capacity_) {
            reserve(n);
            for (size_t i = size_; i < n; i++) {
                new (array_ + i) T();
            }
            size_ = n;
        }
    }

    template <typename T>
    void my_vector<T>::reserve(std::size_t n) {
        if (n > capacity_) {
            size_t new_capacity = (size_t)pow(2, ceil(log2(n)));
            T* new_array = reinterpret_cast<T*>(::operator new(sizeof(T) * new_capacity));

            for (size_t i = 0; i < size_; i++) {
                new (new_array + i) T(array_[i]);
                array_[i].~T();
            }

            capacity_ = new_capacity;
            std::swap(array_, new_array);
            ::operator delete (new_array);
        }
    }
}

服务器测试人员的一些工件:

<system-err>==2162058== Memcheck, a memory error detector
==2162058== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2162058== Using Valgrind-3.18.1 and LibVEX rerun with -h for copyright info
==2162058== Command: lab-11_vector/lab-11_vector test_resize
==2162058== 
==2162058== 
==2162058== HEAP SUMMARY:
==2162058==     in use at exit: 96 bytes in 17 blocks
==2162058==   total heap usage: 119 allocs, 102 frees, 79,640 bytes allocated
==2162058== 
==2162058== 2 bytes in 2 blocks are definitely lost in loss record 1 of 2
==2162058==    at 0x484A2F3: operator new[](unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2162058==    by 0x1109E3: containers::my_vector<Product>::resize(unsigned long) (in /var/lib/gitlab-runner/builds/4WbXJi1U/0/...)
==2162058==    by 0x1127BB: void test_resize<Product>() (in /var/lib/gitlab-runner/builds/4WbXJi1U/0/...)
==2162058==    by 0x10A6C5: main (in /var/lib/gitlab-runner/builds/4WbXJi1U/0/...)
==2162058== 
==2162058== 94 bytes in 15 blocks are definitely lost in loss record 2 of 2
==2162058==    at 0x484A2F3: operator new[](unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2162058==    by 0x10E25A: containers::my_vector<Product>::reserve(unsigned long) (in /var/lib/gitlab-runner/builds/4WbXJi1U/0/...)
==2162058==    by 0x1109A1: containers::my_vector<Product>::resize(unsigned long) (in /var/lib/gitlab-runner/builds/4WbXJi1U/0/...)
==2162058==    by 0x1127BB: void test_resize<Product>() (in /var/lib/gitlab-runner/builds/4WbXJi1U/0/...)
==2162058==    by 0x10A6C5: main (in /var/lib/gitlab-runner/builds/4WbXJi1U/0/...)
==2162058== 
==2162058== LEAK SUMMARY:
==2162058==    definitely lost: 96 bytes in 17 blocks
==2162058==    indirectly lost: 0 bytes in 0 blocks
==2162058==      possibly lost: 0 bytes in 0 blocks
==2162058==    still reachable: 0 bytes in 0 blocks
==2162058==         suppressed: 0 bytes in 0 blocks
==2162058== 
==2162058== For lists of detected and suppressed errors, rerun with: -s
==2162058== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
</system-err>

我认为我的问题是由“my_vector::reserve()”中的“new_array”引起的。如果我遗漏了什么(方法、文件等)请告诉我。

我试图更改此代码:

std::swap(array_, new_array);
::operator delete (new_array);

对此:

operator delete (array_);
array_ = new_array;

但什么都没有改变。

c++ pointers vector
1个回答
0
投票

如果

n
等于零(并且
size_
大于零),请考虑您的代码会发生什么情况。

   if (n <= size_) {
        for (size_t i = size_ - 1; i > n - 1; i--) {
            array_[i].~T();
        }
        size_ = n;
    }

在这种情况下,

n - 1
是整数溢出,因为
n
是无符号的。重写循环以避免这些溢出,像这样

   if (n <= size_) {
        for (size_t i = size_; i > n; i--) {
            array_[i - 1].~T();
        }
        size_ = n;
    }

道德总是非常小心地对无符号值进行减法。

© www.soinside.com 2019 - 2024. All rights reserved.