从堆中删除失败

时间:2019-01-11 03:01:37

标签: c++ c++11

我正在用SSO创建一个字符串,并且当字符串超过23个字符时,我想将指向堆内存的指针存储在堆栈数组中。我遇到的问题是,当我尝试删除分配在堆上的内存时出现错误。我知道我在正确的地址上调用delete,但是失败。谁知道为什么?代码如下:

->clear()

解决方案:在构造函数中,我分配了class kstring { public: kstring() { } kstring(const char* str) { size_ = std::strlen(str); if (size_ + 1 > capacity_) reserve(capacity_ + 1); std::strcpy(data(), str); } void reserve(size_t capacity) { if (capacity <= capacity_ || capacity <= 24) return; char* alloc = new char[capacity]; std::cout << "Alloc: " << static_cast<void*>(alloc) << std::endl; std::copy(data(), data() + size_, alloc); if (on_heap()) delete[] data(); std::memcpy(data_, &alloc, sizeof(char*)); capacity_ = capacity; } char* data() { return capacity_ > 24 ? heap_ptr() : data_; } size_t size() const noexcept { return size_; } size_t capacity() const noexcept { return capacity_; } char& operator[](size_t n) { return data()[n]; } ~kstring() { if (on_heap()) { std::cout << "Deleting: " << static_cast<void*>(data()) << std::endl; delete[] data(); } } bool on_heap() { return capacity_ > 24; } char* heap_ptr() { char* ptr = nullptr; std::memcpy(&ptr, data_, sizeof(char*)); return ptr; } char data_[24] = {0}; private: size_t size_ = 0; size_t capacity_ = 24; }; int main() { { kstring str("Lorem ipsum dolor sit amet, consectetur adipiscing elit"); } return 0; } 个字节而不是capacity_ + 1个字节,导致堆损坏。

1 个答案:

答案 0 :(得分:1)

  kstring(const char* str) 
  {
    size_ = std::strlen(str);
    if (size_ + 1 > capacity_)
       reserve(capacity_ + 1);
    std::strcpy(data(), str);
  }

这有很多问题。

首先,将size_设置为立即可用的大小。但是,如果您查看reserve,它将尝试复制字符串中已有的size_个字节。

第二,您尝试保留的金额为capacity_ + 1。但是没有理由认为这足以容纳您要复制的字符串。

这可能更接近您想要的:

kstring(const char* str) 
{
  size_t new_size = std::strlen(str) + 1;
  if (new_size > capacity_)
     reserve(new_size + 1);
  std::strcpy(data(), str);
  size_ = new_size - 1;
}

请注意,在调用size_之前我们不会更改reserve,因此不会超出范围。还要注意,我们告诉reserve我们需要保留的正确字节数。