triggered breakpoint when trying to deallocate and recreate array dynamically - c++

so the purpose of this code is to delete an array in order to resize it by 1 because I want to add another object to it. The issue is it triggeres a breakpoint when I delete the array.
Car& Car::operator+=(Engine e) {
if (Empty()) {
cout << "The car doesn't have a type! Engine cannot be added!" << endl;
}
else {
if (m_numEngine < 7) {
int newSize = m_numEngine + 1; // New size of array
Car* newArray = nullptr;
newArray = new Engine[newSize]; // Created temporary pointer to store old arrays info into temp one
for (int i = 0; i < m_numEngine; i++) { // Storing old into new
newArray[i] = this->engine[i];
}
newArray[newSize] = e; // Adds e's values into the last index
delete[] engine; // Deletes old array BUT TRIGGER BREAKPOINT OCCURS HERE
engine = newArray; // Stores temp array back into old array so I can return "THIS" object
}
}
return *this;
Error occurs at
"delete[] engine"

changed
newArray[newSize] = e;
to
newArray[m_numEngine++] = e;

Related

c++ How to add value at the beginning of the array and index it?

template <class T>
void DArray<T>::add(T value){
if (currentNum==size){
size=size*2;
delete [] dArray;
}
dArray[0]=value;
currentNum++;
}
I just started to learn c++ and learning all these pointer and dynamic array stuff. Really suffering at how to add the value at the beginning of the array and make the value index to the next one such as position+1. Can anyone point out why my value did pass to only dArray [0] when I use cin but did not index to next position.
int val;
for(int i=1; i<=5; i++){
cout << "Please enter integer value number "<<i<< ": ";
cin >> val;
dInt.add(val);
dInt.printAll();
}
Creating your own container class is actually quite a hairy task. Typically most containers are implemented using global new/delete to allocate raw bytes, and then elements are added by calling placement new.
This code is untested, but should be along the right lines (ish). The code could be improved using std::move, but I'll leave that for now...
template <class T>
void DArray<T>::push_back(const T& value) {
if (currentNum == size) {
// just in case size is zero, or something like that
size = std::max(size + 2, size * 2);
// allocate memory (but don't construct objects, yet)
T* temp = ::operator new (sizeof(T) * size);
// copy construct each element
for(auto i = 0; i < currentNum; ++i)
{
// we have to use placement-new here :/
new (temp + i) T(dArray[i]);
// destroy old item
dArray[i].~T();
}
// free the old memory
::operator delete (dArray);
// update to the new array
dArray = temp;
}
// copy construct the new element
new (dArray + currentNum) T(value);
// increment the count
currentNum++;
}
Adding to the start of the array involves moving each element up in the array. As a result, it's a little bit more involved.
template <class T>
void DArray<T>::push_front(const T& value) {
if (currentNum == size) {
// just in case size is zero, or something like that
size = std::max(size + 2, size * 2);
// allocate memory (but don't construct objects, yet)
T* temp = ::operator new (sizeof(T) * size);
// copy construct each element
// this time iterate in reverse
for(auto i = 0; i < currentNum; ++i)
{
// copy old array into new array (starting at index 1)
new (temp + i + 1) T(dArray[i]);
// destroy old item
dArray[i].~T();
}
// free the old memory
::operator delete (dArray);
// update to the new array
dArray = temp;
}
else
{
// copy old elements in array (traverse in reverse order)
for(auto i = currentNum; i > 0; --i)
{
// construct new item (copying previous element)
new (dArray + i) T(dArray[i - 1]);
// call dtor on old element
dArray[i - 1].~T();
}
}
// construct first element in array
new (dArray) T(value);
// increment the count
currentNum++;
}
... and for completeness, the destructor.
template <class T>
DArray<T>::~DArray()
{
for(auto i = 0; i < currentNum; ++i)
{
// call destructor on each element
dArray[i].~T();
}
// free the memory
::operator delete (dArray);
}
This is a reason most people just end up saying "use std::vector"...

Unable to delete contents of dynamic array in C++

I've been beating my head against this one for awhile. In the deconstructor of my class, I have a for loop that is supposed to iterate through an array of objects and delete them. When I try though, I get a read access violation. The attached code is supposed to read info from two documents and use that to create Country objects.
#include "pch.h"
#include "CountryCatalogue.h"
#include "Country.h"
#include <iterator>
#include <map>
//imports for reading the files
#include <iostream>
#include <fstream>
CountryCatalogue::CountryCatalogue()
{
_maxSize = 10;
_curSize = 0;
_catalogue = new Country*[_maxSize];
}
CountryCatalogue::CountryCatalogue(std::string continentFileName, std::string countryFileName)
{
//block that opens the files and checks to make sure they can be read
//open up the files
std::ifstream inFile1;
std::ifstream inFile2;
//opening both text files and ensuring that the file is readable to the program
inFile1.open(continentFileName);
if (!inFile1) {
std::cout << "Unable to open file";
exit(1); // terminate with error
}
inFile2.open(countryFileName);
if (!inFile2) {
std::cout << "Unable to open file";
exit(1); // terminate with error
}
// read the continet file
// while there is still stuff to read in the file
std::string str;
while (!inFile1.eof())
{
std::string Country, Cont;
//reading lines from file and assigning to variables
std::getline(inFile1, Country);
std::getline(inFile1, Cont);
//mapping to variables read from file
_countryContinent.insert(std::pair<std::string, std::string>(Country, Cont));
_curSize++;
}
//closing file after use
inFile1.close();
//creating array
_catalogue = new Country*[_curSize+2];
//resetting size to zero for later itteration
_curSize = 0;
// read the country file
// while there is still stuff to read in the file
while (!inFile2.eof())
{
std::string name, POP, AREA;
int pop;
double area = 0.0;
std::getline(inFile2, name);
std::getline(inFile2, POP);
std::getline(inFile2, AREA);
if (!POP.empty() && POP[POP.length() - 1] == '\n') {
POP.erase(POP.length() - 1);
}
if (!AREA.empty() && AREA[AREA.length() - 1] == '\n') {
AREA.erase(AREA.length() - 1);
}
pop = std::stoi(POP);
area = std::stod(AREA);
//creating iterator to search through mapped values
std::map<std::string, std::string>::iterator it;
it = _countryContinent.find(name);
//creating empty string variable to store continent
std::string cont;
//using value found by iterator to make continent string
//ensuring value isn't the end valueof the map
if (it != _countryContinent.end()){
cont = it->second;
}
//std::cout << name << pop << area << cont << std::endl;
// add the country to the catalogue
addCountry(name, pop, area, cont);
}
}
CountryCatalogue::~CountryCatalogue() {
/*for (int i = 0; i < _curSize; i++){
delete _catalogue[i];
std::cout << "deleted" << i << std::endl;
}*/
delete[] _catalogue;
}
void CountryCatalogue::addCountry(std::string name, int pop, double area, std::string cont) {
//std::cout << name << pop << area << cont << std::endl;
//std::cout << _curSize << std::endl;
Country* toAdd = new Country(name, pop, area, cont);
if (_curSize == _maxSize) {
expandCapacity();
}
//adding country object to array
_catalogue[_curSize] = toAdd;
//adding to _curSize for next iteration
_curSize++;
}
void CountryCatalogue::printCountryCatalogue() {
std::string s;
/*for (int i = 0; i < _curSize; i++) {
s += _catalogue[i]->to_string() + "\n";
}*/
std::cout << _curSize << std::endl;
}
void CountryCatalogue::expandCapacity() {
//doubling array size
_maxSize = _maxSize * 2;
//creating pointer to new array of new size
Country** newCatalogue = new Country*[_maxSize];
//copying old array into new
for (int i = 0; i < _curSize; i++) {
newCatalogue[i] = _catalogue[i];
}
//deleting old array
delete[] _catalogue;
//making _catalogue point to newCatalogue
_catalogue = newCatalogue;
}
UPDATE:
What my code is supposed to do is get information from text files and create objects using that data. I am required to use an array instead of a vector. The code runs fine and I can create the country object. The issue is that I cannot add the created object to the _catalogue array, as I cannot delete it afterwards. When I attempt to iterate through the array, I receive a message saying Heap Corruption was detected.
Your problem is due to this line
_catalogue = new Country*[_curSize+2];
in the second constructor. You have forgotten to update _maxSize so you have a mismatch between _maxSize and the real allocated amount of memory.
Try:
_maxSize = _curSize+2;
_catalogue = new Country*[_maxSize];
You created _catalogue as a dynamic array.
To release the memory allocated for arrays of elements using new TYPE[SIZE] the syntax is:
delete[] _catalogue;
Loop is Needed for deleting memory allocated for Matrix elements. For example
int matrix = new int[rows][cols];
for (int i = 0; i < rows; ++i)
delete [] matrix[i];
The array is deleted row by row.

Heap corruption detected in C++ on delete[] array after copying it

I'm trying to create a method that create a sort of a dynamic array: when the index exceedes it creates another array with one more element and then it deletes the old one copying the pointer of the new one in the old one. But when I delete the old array I have an HEAP CORRUPTION DETECTED and the program freezes. states is the old array (with 10 items) initializationIndex is used to keep track of the array length.
if (states == nullptr)
states = new int[10];
if (initializationIndex > 10) {
int *tempArr = new int[initializationIndex];
arrayCpy(states, tempArr, initializationIndex - 1);
delete[] states; // HEAP CORRUPTION DETECTED
states = tempArr;
}
if (arrayContains(initializationIndex, states, stateToInsert))
return false;
states[initializationIndex] = stateToInsert;
initializationIndex++;
The function arrayCpy:
void arrayCpy(int * src, int * dst, int offset)
{
int i = 0;
for (i = 0; i < offset; i++) {
dst[i] = src[i];
}
}
you edited the question.
if (states == nullptr)
states = new int[10];
if (initializationIndex > 10) {
int *tempArr = new int[initializationIndex];
arrayCpy(states, tempArr, initializationIndex - 1);
delete[] states; // HEAP CORRUPTION DETECTED
states = tempArr;
}
lets assume initializationIndex = 15, you are doing copy for 14 elements while states size is only 10
delete[] tempArr; // HEAP CORRUPTION DETECTED
states = tempArr;
you delete the array and then use it.
as people said in comments, use std::vector, no need to do new/delete.

I got a glibc detected error

I am trying to create an array that, when filled, will cause a new bigger array to be created, will copy the values of the old array into the previous array, and will continue adding values to the new array from where the old one left off. My code works fine while I'm adding to the first array, but once I try to call append after I've filled up the original array, I end up getting a weird error:
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000602010 ***
No clue what's going on! I'm not really sure why.
#include <iostream>
using namespace std;
class ArrayList {
public:
int* array;
public:
int capacity = 0;
int size = 16;
ArrayList() {
array = new int(size);
}
void append(int data) {
if (size == capacity) {
int* tmp = new int(size+16);
for (int i = 0; i != size; i++) {
tmp[i] = array[i];
delete [] array;
}
array = tmp;
} else {
array[capacity] = data;
capacity++;
// std::cout << *(array+15) << std::endl;
}
Your syntax for allocating an array is wrong - instead of
int* tmp = new int(size+16);
(which creates a new int and initializes it with the value size+16), you need
int* tmp = new int[size+16];
which creates a new int array with size+16 elements.

When to delete class pointer from array

I have a list of pointer object *lst[200];
I use this to add one to it:
object a = new object();
a->id = current_amount;
lst[current_amount] = a;
current_amount++;
now I want to add a function delete it:
I simply want to remove this element from array: (I store an id use it to delete it)
void delete(object *elem)
{
if(!elem)
return;
for (int i = elem->id ; i < current_amount - 1;i++)
{
lst[i] = lst[i + 1];
}
}
Question: When to call delete elem? The code above doesn't free the memory at all...
void deleteElem(object *elem) // you can't call your function 'delete'
{
if(!elem)
return;
for (int i = elem->id ; i < current_amount - 1;i++)
{
lst[i] = lst[i + 1];
}
delete elem; // this free's the memory
}
Since the code above isn't C++, here's some that is:
std::list<std::unique_ptr<object>> lst;
and the methods erase, push_back, push_front.