I am attempting to build a C++ vector from scratch for an assignment, but I've been struggling all day. My append function is broken. At first it would take no string input, but I've gotten it to append one string to the dynamic list. However, when I attempt to append a second string to the list, the temp array is appended with that string, but when I go to delete the existing data attribute array that second time (the previous temp array), I get a segmentation fault. I've included a lot of print statements to pinpoint this.
I have tried instantiating a block of objects using placement new since strings are objects. Here is the DynamicList class.cpp file:
#include <iostream>
#include <string>
#include "DynamicList.hpp"
#include <algorithm>
//Constructor
template<typename T>
DynamicList<T>::DynamicList(){
size = 0;
data = new T[size];
}
//Destructor
template<typename T>
DynamicList<T>::~DynamicList(){
std::cout << "Deleting array of size: " << getSize() << std::endl;
delete[] data;
}
//Overloading operators
template<typename T>
DynamicList<T> DynamicList<T>::operator=(DynamicList<T>& obj){
obj.size = size;
std::copy(data, data + size, obj.data);
}
template<typename T>
bool DynamicList<T>::operator==(DynamicList<T>& obj){
if(size != obj.size){
return false;
}
else{
for(int i = 0; i < size; i++){
if(obj.data[i] != data[i]){
return false;
}
}
return true;
}
}
template<typename T>
bool DynamicList<T>::operator!=(DynamicList<T>& obj){
return !(DynamicList<T>::operator==(obj));
}
template<typename T>
T DynamicList<T>::operator[](int index){
for(int i = 0; i < size; i++){
if(i == index){
return data[i];
}
}
}
//Returns the size of the list
template<typename T>
int DynamicList<T>::getSize(){
return size;
}
//Add element to the end of list.
template<typename T>
bool DynamicList<T>::append(T item){
std::cout << data << std::endl;
std::cout << item << std::endl;
T* temp = static_cast<T*>(new T(sizeof(T) * (size + 1), alignof(T)));
if(size > 1){
for(int i = 0; i < size; i++){
T* somePtr = new (&temp[i]) T;
*somePtr = data[i];
}
}
T* itemPtr = new (&temp[size]) T;
*itemPtr = item;
std::cout << "Ptr made in array slot.\n";
std::cout << temp << std::endl;
size++;
std::cout << "Size increased.\n";
std::cout << data << std::endl;
std::cout << "AAAAAA\n";
delete[] data;
std::cout << "BBBBB\n";
data = temp;
std::cout << data[size - 1] << std::endl;
return true;
}
Here is the header file for DynamicList:
#include <iostream>
#include <string>
#ifndef DYNAMICLIST_H
#define DYNAMICLIST_H
template<typename T>
class DynamicList{
private:
int size;
T* data;
public:
//constructor
DynamicList();
//destructor
~DynamicList();
//Operator overloaders
DynamicList operator=(DynamicList& obj);
bool operator==(DynamicList& obj);
bool operator!=(DynamicList& obj);
T operator[](int index);
//Returns the size of the data array
int getSize();
//Add an item to the end of the list
bool append(T item);
//Remove an item at an index
bool remove(int index);
};
#endif
Here is the main file:
#include <iostream>
#include <string>
#include "DynamicList.hpp"
#include "DynamicList.cpp"
int main(){
DynamicList<std::string> stringList;
stringList.append("test");
stringList.append("test2");
return 0;
}
Here is the makefile:
all: DynamicList.hpp DynamicList.cpp main.cpp
g++ -c DynamicList.cpp
g++ -c main.cpp
g++ DynamicList.o main.o -o exec
run: all
./exec
clean:
rm -f *.o
rm -f exec
Here is the error:
./exec
0x55c688824eb8
test
Ptr made in array slot.
0x55c6888252f0
Size increased.
0x55c688824eb8
AAAAAA
BBBBB
test
0x55c6888252f0
test2
Ptr made in array slot.
0x55c688824eb0
Size increased.
0x55c6888252f0
AAAAAA
make: *** [makefile:8: run] Segmentation fault (core dumped)
The constructor creates the array with array new[]
, but the append function uses object new
instead. Deleting objects created with object new
using array delete[]
or vice versa is undefined behavior.
You should replace the object new
in append
with array new[]
:
template<typename T>
bool DynamicList<T>::append(T item) {
T* temp = new T[size + 1];
for (int i = 0; i < size; i++) {
temp[i] = data[i];
}
temp[size] = item;
size++;
delete[] data;
data = temp;
return true;
}