Question

I have problem with calling delete inside functions. When I allocate memory using new inside function it seem do work, but deleting formerly allocated memory causes throwing of std::bad_alloc. Is it even possible, or can I only free memory under "a" from inside of main?

#include <iostream>

using namespace std;

int size = 5;

void alloc (int* t, char**& a) {
  t = new int [size];
  a = new char* [size];
  for (int i = 0; i < size; ++i)
    a[i] = new char [size];
  cout << "allocated\n";
}

void realloc (char**& a) {
  for(int i = 0; i < size; ++i)
    delete [] a[i];
  delete [] a;
  cout << "deleted\n";
  a = new char* [size];
  for (int i = 0; i < size+5; ++i)
    a[i] = new char [size+5];
  cout << "allocated\n";
}
void fillArray (char** a) {
  for (int i = 0; i < size; ++i) {
    for (int j = 0; j < size; ++j) {
      a[i][j] = '.';
    }
  }
}

void printArray (char** a) {
  for (int i = 0; i < size; ++i) {
    for (int j = 0; j < size; ++j) {
      cout << a[i][j];
    }
    cout << endl;
  }
}
int main() {
  int* t;
  char** a;
  alloc(t, a);
  fillArray(a);
  printArray(a);
  size+=5;
  realloc(a);
  fillArray(a);
  printArray(a);
}
Was it helpful?

Solution

You can call delete[] from anywhere. Your problems are much more prosaic. You just have a defect in your code.

You allocate an array of length size. Then you increment size. Then you do this:

for(int i = 0; i < size; ++i)
    delete [] a[i];

And because you incremented size already, your loop runs off the end of a. You need to use the same value for size as was used when you allocated the array.

To be quite clear, the following is the flow of execution:

  • size is assigned to the value 5.
  • a is allocated with length 5.
  • size is incremented to the value 10.
  • You run a for loop from 0 to size-1, that is 0 to 9, and call delete[] a[i].

Clearly the iterations 5 to 9 inclusive are accessing elements of a that were not allocated. And that's undefined behaviour, and so on.

You could fix this by passing the new size to the realloc function as a parameter. Something like this:

void realloc (char**& a, size_t newsize) {
  for(int i = 0; i < size; ++i)
    delete [] a[i];
  delete [] a;

  size = newsize;
  a = new char* [size];
  for (int i = 0; i < size; ++i)
    a[i] = new char [size];
}

Obviously you would not modify size outside of this function. You would call the function like this:

realloc(a, size+5);

Taking it a bit further, you might choose to handle the allocations like this:

size_t size = 5;

void alloc(char**& a, size_t newsize) {
  size = newsize;
  a = new char*[size];
  for (int i = 0; i < size; ++i)
    a[i] = new char[size];
}

void realloc(char**& a, size_t newsize) {
  for(int i = 0; i < size; ++i)
    delete[] a[i];
  delete[] a;
  alloc(a, size+5);
}

All that said, and being perfectly frank, your entire program is a disaster in the making. There are many other errors that I've not covered in this answer. Use standard containers like std::vector and std::string. The standard containers will handle the details of memory allocation, and will do it correctly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top