Reputation: 334
I tried going through many similar questions regarding munmap_chunk(): invalid pointer
errors, but I'm stuck as to what to do. I tried adding free
commands too.
I'm a C++ novice and normally use Python and Java, so the whole concept of pointers and memory management are new to me. It would be great if someone can explain what I'm doing wrong.
Here is my code for my Array class for a generic T:
#include <iostream>
using namespace std;
template <typename T>
class Array {
private:
T *arr;
int len = 0; //length the user thinks the array is
int capacity = 0; //actual array capacity
public:
Array(int cap=16){
if (cap<0){
throw invalid_argument("Illegal Capacity: "+cap);
}
capacity = cap;
arr = new T[cap];
for(int i=0; i<capacity; i++){
arr[i] = 0;
}
}
~Array(){ delete [] arr; }
T& operator[](int index){ return arr[index]; }
int size(){ return len; }
bool isEmpty(){ return size() == 0; }
T get(int index){ return arr[index]; }
void set(int index, T elem){ arr[index] = elem; }
void clear(){
for(int i = 0; i < capacity; i++)
arr[i] = 0;
len = 0;
}
void add(T elem){
if (len+1 > capacity){
if (capacity == 0) capacity = 1;
else capacity*=2;
T *newarr = new T[capacity];
for (int i = 0; i < len; i++){
newarr[i] = arr[i];
}
delete [] arr;
arr = newarr;
}
arr[len++]=elem;
}
T removeAt(int rmIndex){
if (rmIndex >= len || rmIndex < 0) throw out_of_range(rmIndex +" out of range for len " + len);
T data = arr[rmIndex];
T *newarr = new T[len-1];
for (int i=0, j=0; i < len; i++, j++){
if (i==rmIndex){
j--;
}
else{
newarr[j]=arr[i];
}
}
delete [] arr;
arr = newarr;
capacity = --len;
return data;
}
bool remove(T t){
for (int i=0; i<len; i++){
if (arr[i]==t){
removeAt(i);
return true;
}
}
return false;
}
int indexOf(T t){
for (int i=0; i<len; i++){
if (arr[i]==t){
return i;
}
}
return -1;
}
bool contains(T t){ return indexOf(t) != -1; }
};
int main()
{
cout << "hello" <<endl;
Array<float>z(122);
cout << z.size() << endl;
for (int i = 0; i < z.size(); i++){
z.set(i,(float)i);
}
for (int i = 0; i < z.size(); i++){
cout << z.get(i);
}
cout << z.size() << endl;
return 0;
}
The output is only hello world
without anything else.
I have been learning from this video and I'm trying to convert the Java code given there into C++ in an attempt to learn the language and I've been using StackOverflow extensively for it. For this issue though, I'm unable to find the source of the problem, so please do help me.
The Java code from which this is trying to be adapted into C++ is available here.
Upvotes: 0
Views: 257
Reputation: 2450
The size()
function depends on the len
member being set, which it was not.
You should also be aware that the expression "Illegal Capacity: " + cap
does not append the value of cap
to the end of the string. It does pointer arithmetic and if cap
is less than zero you will be constructing the exception with a pointer to memory before the beginning of the string literal.
Upvotes: 1
Reputation: 334
Thanks to @S.M. @anastaciu and @jkb for their guidance.
The original code posted here was:
#include <iostream>
using namespace std;
template <typename T>
class Array {
private:
T *arr;
int len = 0;
int capacity = 0;
public:
Array(int cap = 16) {
if (cap < 0) {
throw invalid_argument("Illegal Capacity: " + cap);
}
capacity = cap;
arr = new T[cap];
for (int i = 0; i < capacity; i++) {
arr[i] = 0;
}
}
~Array() { delete arr; }
T &operator[](int index) { return arr[index]; }
int size() { return len; }
bool isEmpty() { return size() == 0; }
T get(int index) { return arr[index]; }
void set(int index, T elem) { arr[index] = elem; }
void clear() {
for (int i = 0; i < capacity; i++) arr[i] = 0;
len = 0;
}
void add(T elem) {
if (len + 1 > capacity) {
if (capacity == 0)
capacity = 1;
else
capacity *= 2;
T *newarr = new T[capacity];
for (int i = 0; i < len; i++) {
newarr[i] = arr[i];
}
free(arr);
arr = newarr;
}
arr[len++] = elem;
}
T removeAt(int rmIndex) {
if (rmIndex >= len || rmIndex < 0)
throw out_of_range(rmIndex + " out of range for len " + len);
T data = arr[rmIndex];
T *newarr = new T[len - 1];
for (int i = 0, j = 0; i < len; i++, j++) {
if (i == rmIndex) {
j--;
} else {
newarr[j] = arr[i];
}
}
free(arr);
arr = newarr;
capacity = --len;
return data;
}
bool remove(T t) {
for (int i = 0; i < len; i++) {
if (arr[i] == t) {
removeAt(i);
return true;
}
}
return false;
}
int indexOf(T t) {
for (int i = 0; i < len; i++) {
if (arr[i] == t) {
return i;
}
}
return -1;
}
bool contains(T t) { return indexOf(t) != -1; }
};
int main() {
Array<float> z(122);
for (int i = 0; i < z.size(); i++) {
z.set(i, (float)i);
std::cout << z[i];
}
return 0;
}
Whenever new []
is used, it needs to be paired with a delete []
. free
and delete
should not be used. That is the first issue here, but that's not what causes the code to not work.
The main code never initializes len
and hence when the size()
function is used, it returns 0
, and hence the for loop
is never entered.
The len
needs to be updated every time something is set
as well.
Thus, the main issue is in the logic itself.
Upvotes: 0