0

I have a simple example that imitates a vector. I get the debug assertion failed:

C:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0 Line: 100
Expression: "(_Ptr_user &(_BIG_ALLOCATION_ALIGNMENT -1)) == 0" && 0

This is my example. StrVec.h:

#pragma once
#include <string>
#include <memory>

class StrVec
{
public:
   StrVec();
   StrVec(const StrVec &);
   StrVec &operator=(const StrVec &);
   ~StrVec();

   void push_back(const std::string &s);
   size_t size() const;
   size_t capacity() const;
   std::string *begin() const;
   std::string *end() const;

private:
   void check_volume();
   void reallocate();
   void free();
   std::pair<std::string *, std::string *>
   alloc_n_copy(const std::string *, const std::string *);

   std::string *elements;
   std::string *first_free;
   std::string *cap;
   static std::allocator<std::string> alloc;
};

StrVec.cpp:

#include "stdafx.h"
#include "StrVec.h"

std::allocator<std::string> StrVec::alloc = std::allocator<std::string>();

StrVec::StrVec()
   : elements(nullptr), first_free(nullptr), cap(nullptr) {}

StrVec::StrVec(const StrVec &s) {
   auto newBegin = alloc_n_copy(s.begin(), s.end());
   elements = newBegin.first;
   cap = first_free = newBegin.second;
}

StrVec &StrVec::operator=(const StrVec &rhs) {
   auto newBegin = alloc_n_copy(rhs.begin(), rhs.end());
   free();
   elements = newBegin.first;
   cap = first_free = newBegin.second;
   return *this;
}

StrVec::~StrVec(){
   free();
}

std::pair<std::string *, std::string *>
StrVec::alloc_n_copy(const std::string *b, const std::string *e) {
   auto newMem = alloc.allocate(e - b);
   return{ newMem, std::uninitialized_copy(b, e, newMem) };
}

void StrVec::reallocate() {
   size_t newSize = size() ? 2 * size() : 1;
   auto newBegin = alloc.allocate(newSize);
   auto newPos = newBegin;
   auto oldBegin = elements;
   for (size_t i = 0; i < size(); ++i) {
      alloc.construct(newPos++, std::move(*oldBegin++));
   }
   free();
   elements = newBegin;
   first_free = newPos;
   cap = newBegin + newSize;
}

size_t StrVec::size() const {
   return first_free - elements;
}

size_t StrVec::capacity() const {
   return cap - elements;
}

void StrVec::push_back(const std::string &s) {
   check_volume();
   alloc.construct(first_free++, s);
}

std::string *StrVec::begin() const {
   return elements;
}

std::string *StrVec::end() const {
   return first_free;
}

void StrVec::check_volume() {
   if (size() == capacity()) reallocate();
}

void StrVec::free() {
   if (elements) {
      for (auto p = first_free; p != elements; --p) {
         alloc.destroy(p);
      }
      alloc.deallocate(elements, cap - elements);
   }
}

main.cpp:

int main()
{
   StrVec a;
   a.push_back("abc");
   StrVec b;
   b = a;

   return 0;
}

I have stepped through the code. It failed when return at the main function. I think maybe it's an out-of-range error, but I cannot find the boundary that I have crossed.

Thanks

Zhen Yang
  • 83
  • 9
  • You should be using a simple [copy /swap](https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom) in your `operator =` function instead of all of that code you have now. Right now, it has a huge bug if self-assignment was done, i.e. `a = a;`. – PaulMcKenzie Oct 11 '19 at 12:58
  • Thanks Paul, Even comment out the "b = a", the error is still the same. – Zhen Yang Oct 11 '19 at 13:10
  • I think you should remove the allocator stuff and fix the issues with the basic class, such as the `operator =` using regular `new[] / delete[]` calls. Once you get that class working, then introduce the allocator class. Right now you're trying to add advanced things such as an allocator onto a broken implementation. – PaulMcKenzie Oct 11 '19 at 13:15
  • OK, I will follow you advice and give you feedback later. – Zhen Yang Oct 11 '19 at 13:20
  • @PaulMcKenzie I find that the free function has destroy uninitialized memory. It should be destroy(—p); destroy(p—) lead to undefined behavior. – Zhen Yang Oct 11 '19 at 16:00

1 Answers1

0

It should be destroy(—p) instead of destroy(p—). destroy uninitialized memory on destruction lead to the error.

Zhen Yang
  • 83
  • 9