Adding destructor definition creates running exception - c++

I have a problem with a destructor of struct Heap. Even just adding one, and not using it, creates a runtime exception (memory access). It's second day I try to do it and tomorrow is a deadline.
struct Heap
{
int n;
int* tab;
int* numerWKopcu;
Heap () { n=0; }
Heap (int size) { this->tab = new int[liczbaDomow]; n=0; this->numerWKopcu = new int[2000100];}
int max() { return tab[1]; }
bool empty() { return n==0; }
bool insert(int x)
{
n++;
tab[n]=x;
this->numerWKopcu[x] = n;//ZMIANA
upHeap(n);
return true;
}
bool delMin()
{
if (n<1) return false;
this->numerWKopcu[tab[n]] = 1; //ZMIANA
tab[1]=tab[n]; n--;
downHeap(1);
return true;
}
void upHeap(int x){
int p;
int mem = tab[x];
while (x>1)
{
p=x/2;
if (color[mem]>color[tab[p]]) break;
this->numerWKopcu[tab[p]] = x; //ZMIANA
tab[x]=tab[p];
x=p;
}
this->numerWKopcu[mem] = x;//ZMIANA
tab[x]=mem;
}
void downHeap (int x)
{
int s=2*x;
int mem=tab[x];
while(s<=n)
{
if (s+1<=n && color[tab[s]]>color[tab[s+1]])
s++;
if (color[mem]>color[tab[s]])
{
this->numerWKopcu[tab[s]] = x; //ZMIANA
tab[x]=tab[s];
x=s;
s=2*x;
}
else break;
}
this->numerWKopcu[mem] = x;//ZMIANA
tab[x]=mem;
}
void write ()
{
for (int i=1;i<=n;i++) printf ("%d) %d\n", i, tab[i]);
printf ("\n");
}
void build()
{
int s = n;
for (s=n/2; s>=1; s--) downHeap(s);
}
/ ~Heap() {
delete []this->numerWKopcu;
delete []this-> tab;
};
};

The code is a bit hard to read, but I see two problems:
You aren't initialising the pointers to null in the default constructor, so destroying a default-constructed object gives undefined behaviour;
You don't define or remove the copy constructor and copy assignment operator (as you should always do if you define a destructor, per the Rule of Three), so destroying a copied object gives undefined behaviour.
It's also possible that you're accessing memory outside the array bounds; a memory debugging tool such as valgrind can help you determine whether that's happening.
The simplest solution is to replace your manually-managed arrays with std::vector; then you won't need to worry about writing your own destructors or copy semantics. You can also use at() rather than [] (at least in a debug variant) to give range-checked access.

You are not initializing pointers in default constructor. If you try to destroy default constructed Heap it will try to delete random memory areas in destructor and will definitely break.

Related

C API: Error allocating / deallocating memory for array

I'm in the process of implementing an API for C. The code base itself is purely written in C++ and I only plan to offer said interface for any consumer using C. The interface is defined in a .h file, whereas the implementation itself is written in C++. I've read multiple times that using C++ to implement a C interface is not the best idea, but it works great in my case.
Anyway the header definition looks similar to this:
extern 'C' {
typedef struct Person {
const char *name;
uint32_t age;
uint32_t post_code;
} Person;
typedef struct PersonArray {
Person *person;
size_t size;
} PersonArray;
PersonArray *create(size_t size);
void destroy(PersonArray *array);
int fillArray(PersonArray *array);
}
I'd like the consumer to retrieve a handle for PersonArray, which contains an array of Person structure, allocated with the size passed to the create() function.
Since the implementation is in C++ I've tried to allocate the memory the following way:
static inline Person convert(const otherNamespace::Person &o_person) {
Person p{};
p.name = o_person.name;
p.age = o_person.age;
p.post_code = o_person.post_code;
return p;
}
PersonArray *create(size_t size) {
if (size <= 0) {
return nullptr;
}
PersonArray *array = new PersonArray();
array->size = size;
array->person = new Person[size]
return array;
}
void destory(PersonArray *array) {
delete array;
}
int fillArray(PersonArray *array) {
if (array == nullptr) {
return 1;
}
auto data = // retrieve std::vector<otherNamespace::Person> via RPC
for (auto i{0U}; i < array->size; i++) {
array->person[i] = convert(data.at(i);
}
return 0;
}
Unfortunately, this approach does not seem to work correctly, because when using a memchecker like valgrind, there are still blocks on the heap that are not correctly deallocated. I suppose the line new Person[size] does not get deallocated.
Any idea how to fix this memory leak? Or is there another design which would be better suited for this specific use case? If possible, I would really like to keep the implementation in C++.
You must use delete on person before array, but since it was allocated with new [] you must delete it with delete [].
void destroy(PersonArray *array) {
if (array) {
if (array->person) {
delete [] array->person;
}
delete array;
}
}

C++ how to call D'tor?

I wrote:
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) { // allocation failed for one node (Doesn't throw any exception)
~UnLabeledList();
delete[] SegArray;
throw;
}
SegArray[i] = NOT_INIT;
}
};
};
In case one allocation failed I want to destroy the object (since it has previously allocated nodes) for example when allocation fails at i==5. How can I call the d'tor of UnLabeledListto prevent memory leak?
You should never call a destructor yourself to clean up things. The language rules take care of it.
It is recommended to use standard classes like std::vector and std::list rather than raw arrays/pointers and homebrew lists. The standard classes already take care of exceptions and cleanup, so your class should look something like
class image {
public:
std::list<std::pair<int, int>> UnLabeledList;
std::vector<int> SegArray;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(Segments, NOT_INIT), TotalSegments(Segments) {
for (int i = 0; i < Segments; ++i) {
UnLabeledList.push_back({i, NOT_INIT});
}
};
};
You can't directly invoke the destructor of the UnLabeledList member like that.
If the image constructor throws an uncaught exception, the UnLabeledList member will be destructed automatically, if it was successfully constructed before the exception was thrown.
The correct solution is to implement a clear() method in the linked_list class, which you can call whenever needed, including in the copy constructor and destructor. For example:
template<...>
class linked_list {
// ...
public:
linked_list() {
// initialize the list as needed...
}
linked_list(const linked_list &src) : linked_list() {
for (each node in src) {
if (!push_back(...)) {
clear();
throw ...;
}
}
}
~linked_list() {
clear();
}
linked_list& operator=(const linked_list &rhs) {
// clear and copy the list as needed...
}
void clear() {
// free nodes as needed...
}
node* push_back(...) {
// add new node as needed...
return ...; // nullptr on error
}
//...
};
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw ...; // <-- UnLabeledList::~linked_list() called automatically!
}
SegArray[i] = NOT_INIT;
}
~image() {
delete[] SegArray;
} // <-- UnLabeledList::~linked_list() called automatically!
};
You also can't call a parameter-less throw; outside of an active catch handler. Outside of a catch, you must throw an actual value/object explicitly.
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw std::runtime_error("can't push a new node");
}

Memory leak after pointing to NEW object

struct StructA {
StructA(parameters) { ... } //StructA onstructor
};
struct StructB {
StructA *pObjectA;
int counter = 0;
void function() {
if (counter < 1) { pObjectA = new StructA[100]; }
pObjectA[counter] = *new StructA(parameters); //Memory leak here
counter++;
}
};
struct StructC {
StructB objectB;
~StructC() { //StructC destructor
delete[] objectB.pObjectA;
objectB.pObjectA = NULL;
}
};
int main() {
StructC objectC;
for (int i = 0; i < 900; i++) {
objectC.objectB.function();
}
return 0;
} //Struct C destructor here
I need to create an object array and then, with each call to objectB.function(), to pass specific parameters to the constructor of StructA. The code above works perfectly, except for the memory leak, which I am unable to get rid of.
My guess is that the StructC destructor deletes only the object array, not each *new StructA(parameters). I tried to play around with pointers and delete[] a little bit, but all I got was access memory violation errors. This is the only way I can think of that works. All help appreciated.
A class destructor should release resources that were acquired in its constructor. It seems like you wanted to defer deleting an array allocated in one class to the destructor of a second class. Thats never a good idea. In the best case you dont have to do anything in the destructor because you use automatic storage (means what the name suggest: memory is managed automatically).
Your code could look like this:
struct StructA {
StructA(parameters) { ... } //StructA onstructor
};
struct StructB {
std::vector<StructA> pObjectA;
int counter = 0;
void function() {
if (counter < 1) { pObjectA.reserve(100); }
pObjectA.emplace_back(parameters);
counter++;
}
};
struct StructC {
StructB objectB;
};
int main() {
StructC objectC;
for (int i = 0; i < 900; i++) {
objectC.objectB.function();
}
return 0;
}
Note that I tried to keep the structure as is maybe there are other things to change. For example you dont need counter, as you can use std::vector::size to query the number of elements in the vector.
PS: As you already noticed, this is a memory leak:
pObjectA[counter] = *new StructA(parameters); //Memory leak here
It is not really clear why you wrote that code in the first place. The idomatic way to create an object of type StructA is StructA a; (no new!).
As you correctly assumed, memory leaks are caused by not properly cleaning up all new with corresponsing delete. However in idiomatic C++ there's no use to use new and delete directly.
Use std::vector, std::shared_ptr and std::unique_ptr to let RAII keep track of dynamically created objects, references to them and when to clean up. Not only is it more robust, it's also a lot shorter and easier to read.
With your code's general overall structure:
#include <memory>
#include <vector>
struct StructA {
};
struct StructB {
std::vector<std::shared_ptr<StructA>> objectAs;
void function() {
objectAs.push_back(
std::make_shared<StructA>( /*parameters*/ )
);
}
};
struct StructC {
StructB objectB;
};
int main() {
StructC objectC;
for (int i = 0; i < 900; i++) {
objectC.objectB.function();
}
return 0;
}

Unusual C++ behaviour when calling constructor

In an effort to become a more competent C++ programmer I'm experimenting w/ using references. In the past I have usually used pointers when referring to objects, as you would for example in Objective-C.
So I've been programming a Polynomial class that stores a list of Term objects
(TermNode* termHead,termTail)
But when I try to add a term to the list using the first implementation listed, calling the constructor on Term in add term, overwrites the Term& reference in the previously created Term node, as if it used the this pointer from the previous invocation of the constructor.
What is technically wrong about the first implementation listed, that causes it to behave so abnormally? It just works when I use pointers and new even though I do not change the structure of TermNode.
struct TermNode {
Term& value;
TermNode* next;
};
Term::Term(int coefficient,int firstTermDegrees,int secondTermDegrees) {
this->coefficient = coefficient;
this->xDegree = firstTermDegrees;
this->yDegree = secondTermDegrees;
}
//Doesn't work
void Polynomial::addTerm(int coefficient, int xDegree, int yDegree) {
Term term(coefficient,xDegree,yDegree);
addTerm(term);
}
void Polynomial::addTerm(Term& term) {
TermNode* t = new TermNode{term,nullptr};
if(isEmpty())
{
termHead = t;
termTail = t;
}
else
{
termTail->next = t;
termTail = termTail->next;
}
}
//Does work
void Polynomial::addTerm(int coefficient, int xDegree, int yDegree) {
Term* term = new Term(coefficient,xDegree,yDegree);
addTerm(term);
}
void Polynomial::addTerm(Term* term) {
TermNode* t = new TermNode{*term,nullptr};
if(isEmpty())
{
termHead = t;
termTail = t;
}
else
{
termTail->next = t;
termTail = termTail->next;
}
}
bool isEmpty() {
return nullptr == termHead;
}
//Doesn't work
void Polynomial::addTerm(int coefficient, int xDegree, int yDegree)
{
Term term(coefficient,xDegree,yDegree);//here you created automatic object
addTerm(term); //it will be deleted in next line
} //it is an error to call addTerm(Term& term)
this works
//Does work
void Polynomial::addTerm(int coefficient, int xDegree, int yDegree)
{
Term* term = new Term(coefficient,xDegree,yDegree);
addTerm(term);
}
because here you created object on a free store. It's life is extended till you call delete on it (side note: call delete somewhere, at this moment you have a memory leak! or use smart pointer), so this works just fine.
void Polynomial::addTerm(Term* term)
{
TermNode* t = new TermNode{*term,nullptr};
// ...
}
You can use references but in the way they are supposed to be used. You can't use a reference to temporary when it was actually deleted. You can bind temporary object to const reference however, but because of your struct definition
struct TermNode
{
Term& value;
TermNode* next;
};
in constructor you take a reference again, so binding temporary to const reference in this case will again result in segmentation fault.
In the first implementation you passes a reference to a temporary object which is destroyed at the end of method addTerm.

Unable to exit as destructor errors cause execution of main() to halt upon exit

I have narrowed my problem down to passing 2 objects (which contain pointer data members) to a simple void function. The function returns clean, but when main() attempts to exit, it can not reclaim the first of the 2 objects. Here is a sample piece of code that shows the issue - along with print statements to show the address's of the objects as they are constructed, passed, and destructed.
If I only call "print1" - the program runs fine. However, if I call "printboth" - then the object "myNumbers" can not be freed. I can also make the error go away by removing the destructor statement:
delete [] number;
but I don't think this is a good idea.
Anyone have any ideas?
class dummy
{
public:
dummy() {
number = new int[1];
currentPos = -1;
std::cout<<"default constructor called for "<<this<<std::endl;
}
dummy(int len) {
number = new int[len];
currentPos = -1;
std::cout<<"parameterized constructor called for "<<this<<std::endl;
}
~dummy() {
cout<<"Calling destructor for "<<this<<endl;
delete [] number;
}
int getNextNumber() {
currentPos++;
return number[currentPos];
}
void setNumbers(int position, int value) {
number[position] = value;
}
private:
int* number;
int currentPos;
};
void print1(dummy);
void printboth(dummy, dummy);
int main() {
dummy myNumbers(3);
myNumbers.setNumbers(0,0);
myNumbers.setNumbers(1,1);
dummy myOtherNumbers(3);
myOtherNumbers.setNumbers(0,4);
myOtherNumbers.setNumbers(1,5);
cout<<"Address of myNumbers is "<<&myNumbers<<endl;
cout<<"Address of myOtherNumbers is "<<&myOtherNumbers<<endl;
print1(myNumbers);
printboth(myNumbers, myOtherNumbers);
system("PAUSE");
return 0;
}
void print1(dummy num) {
cout<<"Address of num is "<<&num<<endl;
for (int i=0;i<4;i++)
cout<<"Dummy number1 is "<<num.getNextNumber()<<endl;
return;
}
void printboth(dummy num1, dummy num2) {
cout<<"Address of num1 is "<<&num1<<endl;
cout<<"Address of num2 is "<<&num2<<endl;
for (int i=0;i<4;i++) {
cout<<"Dummy number1 is "<<num1.getNextNumber()<<endl;
cout<<"Dummy number2 is "<<num2.getNextNumber()<<endl;
}
return;
}
You didn't follow rule of three
The problem is that when you call print1 or printboth the compiler calls the default copy-constructor (since you didn't provide one). That copy-constructor sets the number member variable of the copy to the same value as the original. When the destructor is called on the copy, the memory is released. Your original object now points to memory that has already been released so when its destructor is called, you crash(Nik Bougalis).
void print1(dummy);
void printboth(dummy, dummy);
You could pass dummy by const reference to avoid unnecessary copy, but strong recommand you follow rule of three
void print1(const dummy& );
void printboth(const dummy&, const dummy&);
Note:
You only created size =1 array which is not necessary at all, just use int number; as member. If number holds dynamically allocated array, try use std::vector<int>.
getNextNumber is flawed, when it's called multiple times, number[currentPos]; access boundry out of number which is undefined behavior.
int getNextNumber() {
currentPos++;
return number[currentPos];
}
Which implies what suggested:
int getNextNumber() const {
return number[currentPos];
}