Tony.v
Tony.v

Reputation: 3

I cant get my destructor to work in my code

Like i said in the title i cant get the destructor to work. The reason being is that in this program i am required to use a int* array with negative indices: I keep getting this error at random times while running also: Microsoft C++ exception: std::bad_alloc at memory location 0x009DF130. heres the code that i believe involves the error:

private: int* run;
IntArray::IntArray(int a, int b)
{
    int c = b-a;
    run = new int [c] + a; //This is how i give it a negative indicie
    h = b;
    l = a;
}
IntArray::~IntArray()
{
    delete[]run;
}
string IntArray::setName(string sp)
{
    s = sp;
    return s;
}
void runSim() {
    IntArray b(-4, 6);
    for (int i = b.low(); i <= b.high(); i++)
    // low is the lowes bound high  is the highest
        b[i] = i * 10;
    b.setName("b"); //this is where it breaks and gives me that error
    wait();
}

Upvotes: 0

Views: 94

Answers (4)

Ben Voigt
Ben Voigt

Reputation: 283803

The only right way to do this is to define a custom operator[] on your class. The code you have has numerous errors:

  1. You access both low and high, that's high-low+1 elements. But you only allocate high-low.
  2. If p=new int[high-low+1], then run=p+low; and run[low] means *(p + low + low). This is the proximate cause of your crash -- you wrote way outside the array, trashing internal metadata, which made dynamic allocation fail for the next user, your string's assignment operator.
  3. You should have subtracted low when computing run, so that run[low] would give p[0], the first allocated element. But this might calculate a pointer outside the array (when low is positive), which is undefined behavior.
  4. You pass a pointer to delete[] that didn't come from array new. You need to pass p, not run, to delete[].
  5. You have no attempt at exception safety. Management of dynamic memory in C++ is an advanced topic, and the evidence shows that you are not ready to do it yet. So use an existing smart pointer to manage your memory.

Here's a better version:

#include <memory>

template<typename T>
class ArbBoundArray
{
    int low;
    std::unique_ptr<T[]> base;

public:
     ArbBoundArray(int l, int h) : low(l), base(new T[h-l+1]) {}
     T& operator[](int o) { return base[o-low]; }
     const T& operator[](int o) const { return base[o-low]; }
};

That's it. Less code, works for any type not just int, and exception-safe.

You can add your special needs like a name or whatever on top of that basic concept.

Upvotes: 4

RamblingMad
RamblingMad

Reputation: 5528

Not trying to be mean, but this is pretty bad code.

First of all, if b - a returns a number less than 0 you will probably get an std::bad_alloc and if a > c you will be stepping into undefined behaviour [scary] territory and will probably get a segfault if you try to use the pointer.

Seeing as though you try to delete[] the pointer that points to new int[c] + a you almost certainly will get a segfault.

You need to do run -= a before trying to delete[] it, the implementation will either store information about any new or malloc in the space before the pointer that you get given so that when you delete or free the memory it just has to run behind the pointer and get any information it needs or store the info in a hidden array somewhere that is indexed by the numerical representation of the pointer. But probably the first. Either way, you're screwed doing what you're doing.

Upvotes: 1

Deduplicator
Deduplicator

Reputation: 45694

Your have a simple errors:

Do not pass a value to delete [] you didn't get from new [] (or already passed once).

You need to undo your pointer-arithmetic to get the right pointer.

Also, be aware that if you create a pointer which points outside the array using pointer-arithmetic, you have Undefined Behavior.

If that's not your actual code, beware of trying to allocate less than 1 element.

Upvotes: 3

John Zwinck
John Zwinck

Reputation: 249582

Since you add a (aka l) to run when you new it, you must subtract when you delete it:

delete[] (run - l);

Upvotes: 1

Related Questions