Using vectors to initialize object arrays for parameterized constructors - c++

I am working with Visual Studio 2010 and am relatively new to C++. The program I am trying to work with has a class with a parameterized constructor and a destructor in its declaration. Somewhere in the listing, there was a dynamic object array creation using 'new'. However, I faced issues as object array initialization for parameterized constructors is not possible.
I have, thus, tried to implement vectors:
std::vector< class_type > my_object_array(length, arg); //current attempt
my_object_array = new class_type[length](arg); //previous code
However, once this object array is created, a ~vector destructor is called and I receive a runtime error of "Debug Assertion Failed... _BLOCK_TYPE_IS_VALID (pHead->nBlockUse)"
Based on previous such questions on SO, I think this is because of double deletion but I have not called the destructor explicitly during the debugging steps and I still receive this error.
Any help is appreciated! Thanks!
Edit: Added some snippets of the code with names changed.
class class_type {
public:
class_type(int var1);
~Class_type();
/*
Member functions
*/
private:
int var1;
double var2;
double length;
double width;
double* arr1;
};
Constructor definition:
Class_type::Class_type(int il){
length = 0;
width = 0;
var1 = il;
var2 = 5;
arr1 = new double[5];
}
Destructor definition:
Class_type::~Class_type(){
delete [] arr1;}
Code where error occurs:
int class_type_2::create_my_objects(int num_elem){
input_value = 10;
if ( num_elem == 0 ) {
std::cout<<"Warning!"<<endl;
} else {
std::vector<class_type> my_object_array(num_elem, input_value);
//my_object_array= new class_type[num_elem](input_value);
} //Debugger doesn't go beyond this step!
return 0;
}

std::vector my_object_array(length, arg); //current attempt
Your vector might be out of scope as much as you wrote is just one line. So, it's not possible to reply exact cause what happened to yours. I think you might pass the vector to another copy constructor or move constructor where it deletes the memory and calls the destructor.
As #Matthieu Brucher just said you should manage memory by yourself if allocated using "new". Otherwise double deletion is a common issue and may other memory issues may occur.
Edit1:
I just updated after seeing your code
std::vector<class_type> my_object_array(num_elem, input_value);
} ---> when this scope hits it will release all stacked memory inside it and call their object constructors
Initialize the raw pointer with nullptr.
double* arr1; // you have written
double* arr1 = nullptr; // recommended
Edit 2:
you can delete a memory if allocated with malloc() or calloc(). otherwise use vector. it will manage your memory without leak.

If you use a std::unique_ptr for your object instead of the double*, you will see that your code doesn't compile anymore. This indicates that the code you have uses the default copy constructor, and the pointer will be copied to a copied class.
Unfortunately, this means that several objects will have the same pointer and try to free it, which will fail. If you follow good c++ practices and never call new and delete yourself, you won't see these issues anymore, because they will force you to think properly from the start.

Related

C++ class destructor not being called automatically causes memory leak?

(Before anyone asks: no, i didn't forget the delete[] statement)
I was fiddling around with dinamically allocated memory and i run into this issue. I think the best way to explain it is to show you these two pieces of code I wrote. They are very similar, but in one of them my class destructor doesn't get called.
// memleak.cpp
#include <vector>
using namespace std;
class Leak {
vector<int*> list;
public:
void init() {
for (int i = 0; i < 10; i++) {
list.push_back(new int[2] {i, i});
}
}
Leak() = default;
~Leak() {
for (auto &i : list) {
delete[] i;
}
}
};
int main() {
Leak leak;
while (true) {
// I tried explicitly calling the destructor as well,
// but this somehow causes the same memory to be deleted twice
// and segfaults
// leak.~Leak();
leak = Leak();
leak.init();
}
}
// noleak.cpp
#include <vector>
using namespace std;
class Leak {
vector<int*> list;
public:
Leak() {
for (int i = 0; i < 10; i++) {
list.push_back(new int[2] {i, i});
}
};
~Leak() {
for (auto &i : list) {
delete[] i;
}
}
};
int main() {
Leak leak;
while (true) {
leak = Leak();
}
}
I compiled them both with g++ filename.cpp --std=c++14 && ./a.out and used top to check memory usage.
As you can see, the only difference is that, in memleak.cpp, the class constructor doesn't do anything and there is an init() function that does its job. However, if you try this out, you will see that this somehow interferes with the destructor being called and causes a memory leak.
Am i missing something obvious? Thanks in advance.
Also, before anyone suggests not using dinamically allocated memory: I knwow that it isn't always a good practice and so on, but the main thing I'm interested in right now is understanding why my code doesn't work as expected.
This is constructing a temporary object and then assigning it. Since you didn't write an assignment operator, you get a default one. The default one just copies the vector list.
In the first code you have:
Create a temporary Leak object. It has no pointers in its vector.
Assign the temporary object to the leak object. This copies the vector (overwriting the old one)
Delete the temporary object, this deletes 0 pointers since its vector is empty.
Allocate a bunch of memory and store the pointers in the vector.
Repeat.
In the second code you have:
Create a temporary Leak object. Allocate some memory and store the pointers in its vector.
Assign the temporary object to the leak object. This copies the vector (overwriting the old one)
Delete the temporary object, this deletes the 10 pointers in the temporary object's vector.
Repeat.
Note that after leak = Leak(); the same pointers that were in the temporary object's vector are also in leak's vector. Even if they were deleted.
To fix this, you should write an operator = for your class. The rule of 3 is a way to remember that if you have a destructor, you usually need to also write a copy constructor and copy assignment operator. (Since C++11 you can optionally also write a move constructor and move assignment operator, making it the rule of 5)
Your assignment operator would delete the pointers in the vector, clear the vector, allocate new memory to hold the int values from the object being assigned, put those pointers in the vector, and copy the int values. So that the old pointers are cleaned up, and the object being assigned to becomes a copy of the object being assigned from, without sharing the same pointers.
Your class doesn't respect the rule of 3/5/0. The default-generated move-assignment copy-assignment operator in leak = Leak(); makes leak reference the contents of the temporary Leak object, which it deletes promptly at the end of its lifetime, leaving leak with dangling pointers which it will later try to delete again.
Note: this could have gone unnoticed if your implementation of std::vector systematically emptied the original vector upon moving, but that is not guaranteed.
Note 2: the striked out parts above I wrote without realizing that, as StoryTeller pointed out to me, your class does not generate a move-assignment operator because it has a user-declared destructor. A copy-assignment operator is generated and used instead.
Use smart pointers and containers to model your classes (std::vector<std::array<int, 2>>, std::vector<std::vector<int>> or std::vector<std::unique_ptr<int[]>>). Do not use new, delete and raw owning pointers. In the exceedingly rare case where you may need them, be sure to encapsulate them tightly and to carefully apply the aforementioned rule of 3/5/0 (including exception handling).

segmentation fault at the end of the destructor on deleting integer pointer

I am trying to understand the below program . While executing am getting errors as shown below.
#include<iostream>
using namespace std;
class Base
{
public:
int *a;
int a1;
int b;
Base(){
cout<<"Inside Constructor"<<endl;
a1 = 10;
a = &a1;
cout<<" "<<a<<endl;
b = 20;
}
Base(const Base &rhs)
{
cout<<"Inside Copy Constructor"<<endl;
a = new int;
*a = *(rhs.a);
b = rhs.b;
}
~Base(void)
{
cout<<"Inside destructor"<<endl;
delete a;
}
};
int main()
{
Base obj;
Base obj2(obj);
cout<<"obj a "<<*(obj.a)<<" b "<<obj.b<<endl;
cout<<"obj2 a "<<*(obj2.a)<<" b "<<obj2.b<<endl;
obj.a1 = 30;
obj.b = 40;
cout<<"obj a "<<*(obj.a)<<" b "<<obj.b<<endl;
cout<<"obj2 a "<<*(obj2.a)<<" b "<<obj2.b<<endl;
return 0;
}
While executing this code i am getting the following output
Inside Constructor
Inside Copy Constructor
obj a 10 b 20
obj2 a 10 b 20
obj a 30 b 40
obj2 a 10 b 20
Inside destructor
Inside destructor
Segmentation fault
[EDIT]
I was looking for a way to destruct the heap memory that i have created in copy constructor . So what can be done here ? please suggest
[EDIT]
delete should be used on memory allocated from heap using new only.
a1 = 10;
a = &a1;
In your case "a" is holding the address of memory in stack. So, you shouldn't call delete on that memory.
You have to delete memory acquired with new (dynamically allocated), not to an automatic-storage variable.
In copy constructor you are using new operator to assign the memory for pointer a ,so u can delete it.But since u are not using new operator in default constructor, you can delete the pointer a .
You must use delete opearator to free the memory of variable which is in heap not in stack.
when you use new operator ,the variable is created in heap where as local variable are created in stack memory which can't be delete using delete operator
The problem is not the copy constructor, the problem is that you don't consistently use new (if you used move then maybe you would have a point). You have some options. I am trying to be useful, not exhaustive, maybe I'm missing other good design ideas.
Use new always (and consistently)
You can put a new in all the constructors, and thus, the destructor would always be able to call to delete. Even when you don't need it. It may be a ugly hack, but is consistent.
Never use new
If you never use new, you don't use delete either and the compiler ensures consistency and ensures that you don't mess up. Normally, you can rely on the compiler default behaviour on constructors.
Use smart pointers
If instead of calling to delete manually you save the variable inside a unique_ptr, then it will be deallocated at the destructor automatically by the compiler. The smart pointer is smart enough to know if it is initialized.
Beware that using a smart pointer means that you should never call delete, because if you do so without warning the smart pointer, you will stumble onto the same problem. If you are not familiarized with them and you are using C++11, it is a nice thing to learn :)
Track the status of your pointers
I would not vouch for this. It seems very C and not C++. However, you can always track a bool value and at destroy time check it. This is just like using smart pointers, but with an in-house implementation. I think that it is a bad design idea, although educational in some cases.

double free without any dynamic memory allocation

In general, what could cause a double free in a program that is does not contain any dynamic memory allocation?
To be more precise, none of my code uses dynamic allocation. I'm using STL, but it's much more likely to be something I did wrong than for it to be a broken implmentation of G++/glibc/STL.
I've searched around trying to find an answer to this, but I wasn't able to find any example of this error being generated without any dynamic memory allocations.
I'd love to share the code that was generating this error, but I'm not permitted to release it and I don't know how to reduce the problem to something small enough to be given here. I'll do my best to describe the gist of what my code was doing.
The error was being thrown when leaving a function, and the stack trace showed that it was coming from the destructor of a std::vector<std::set<std::string>>. Some number of elements in the vector were being initialized by emplace_back(). In a last ditch attempt, I changed it to push_back({{}}) and the problem went away. The problem could also be avoided by setting the environment variable MALLOC_CHECK_=2. By my understanding, that environment variable should have caused glibc to abort with more information rather than cause the error to go away.
This question is only being asked to serve my curiosity, so I'll settle for a shot in the dark answer. The best I have been able to come up with is that it was a compiler bug, but it's always my fault.
In general, what could cause a double free in a program that is does not contain any dynamic memory allocation?
Normally when you make a copy of a type which dynamically allocates memory but doesn't follow rule of three
struct Type
{
Type() : ptr = new int(3) { }
~Type() { delete ptr; }
// no copy constructor is defined
// no copy assign operator is defined
private:
int * ptr;
};
void func()
{
{
std::vector<Type> objs;
Type t; // allocates ptr
objs.push_back(t); // make a copy of t, now t->ptr and objs[0]->ptr point to same memory location
// when this scope finishes, t will be destroyed, its destructor will be called and it will try to delete ptr;
// objs go out of scope, elements in objs will be destroyed, their destructors are called, and delete ptr; will be executed again. That's double free on same pointer.
}
}
I extracted a presentable example showcasing the fault I made that led to the "double free or corruption" runtime error. Note that the struct doesn't explicitly use any dynamic memory allocations, however internally std::vector does (as its content can grow to accommodate more items). Therefor, this issue was a bit hard to diagnose as it doesn't violate 'the rule of 3' principle.
#include <vector>
#include <string.h>
typedef struct message {
std::vector<int> options;
void push(int o) { this->options.push_back(o); }
} message;
int main( int argc, const char* argv[] )
{
message m;
m.push(1);
m.push(2);
message m_copy;
memcpy(&m_copy, &m, sizeof(m));
//m_copy = m; // This is the correct method for copying object instances, it calls the default assignment operator generated 'behind the scenes' by the compiler
}
When main() returns m_copy is destroyed, which calls the std::vector destructor. This tries to delete memory that was already freed when the m object was destroyed.
Ironically, I was actually using memcpy to try and achieve a 'deep copy'. This is where the fault lies in my case. My guess is that by using the assignment operator, all the members of message.options are actually copied to "newly allocated memory" whereas memcpy would only copy those members that were allocated at compile time (e.g. a uint32_t size member). See Will memcpy or memmove cause problems copying classes?. Obviously this also applies to structs with non-fundamental typed members (as is the case here).
Maybe you also copied a std::vector incorrectly and saw the same behavior, maybe you didn't. In the end, it was my entirely my fault :).

Double free or corruption after queue::push

#include <queue>
using namespace std;
class Test{
int *myArray;
public:
Test(){
myArray = new int[10];
}
~Test(){
delete[] myArray;
}
};
int main(){
queue<Test> q
Test t;
q.push(t);
}
After I run this, I get a runtime error "double free or corruption". If I get rid of the destructor content (the delete) it works fine. What's wrong?
Let's talk about copying objects in C++.
Test t;, calls the default constructor, which allocates a new array of integers. This is fine, and your expected behavior.
Trouble comes when you push t into your queue using q.push(t). If you're familiar with Java, C#, or almost any other object-oriented language, you might expect the object you created earler to be added to the queue, but C++ doesn't work that way.
When we take a look at std::queue::push method, we see that the element that gets added to the queue is "initialized to a copy of x." It's actually a brand new object that uses the copy constructor to duplicate every member of your original Test object to make a new Test.
Your C++ compiler generates a copy constructor for you by default! That's pretty handy, but causes problems with pointer members. In your example, remember that int *myArray is just a memory address; when the value of myArray is copied from the old object to the new one, you'll now have two objects pointing to the same array in memory. This isn't intrinsically bad, but the destructor will then try to delete the same array twice, hence the "double free or corruption" runtime error.
How do I fix it?
The first step is to implement a copy constructor, which can safely copy the data from one object to another. For simplicity, it could look something like this:
Test(const Test& other){
myArray = new int[10];
memcpy( myArray, other.myArray, 10 );
}
Now when you're copying Test objects, a new array will be allocated for the new object, and the values of the array will be copied as well.
We're not completely out trouble yet, though. There's another method that the compiler generates for you that could lead to similar problems - assignment. The difference is that with assignment, we already have an existing object whose memory needs to be managed appropriately. Here's a basic assignment operator implementation:
Test& operator= (const Test& other){
if (this != &other) {
memcpy( myArray, other.myArray, 10 );
}
return *this;
}
The important part here is that we're copying the data from the other array into this object's array, keeping each object's memory separate. We also have a check for self-assignment; otherwise, we'd be copying from ourselves to ourselves, which may throw an error (not sure what it's supposed to do). If we were deleting and allocating more memory, the self-assignment check prevents us from deleting memory from which we need to copy.
The problem is that your class contains a managed RAW pointer but does not implement the rule of three (five in C++11). As a result you are getting (expectedly) a double delete because of copying.
If you are learning you should learn how to implement the rule of three (five). But that is not the correct solution to this problem. You should be using standard container objects rather than try to manage your own internal container. The exact container will depend on what you are trying to do but std::vector is a good default (and you can change afterwords if it is not opimal).
#include <queue>
#include <vector>
class Test{
std::vector<int> myArray;
public:
Test(): myArray(10){
}
};
int main(){
queue<Test> q
Test t;
q.push(t);
}
The reason you should use a standard container is the separation of concerns. Your class should be concerned with either business logic or resource management (not both). Assuming Test is some class you are using to maintain some state about your program then it is business logic and it should not be doing resource management. If on the other hand Test is supposed to manage an array then you probably need to learn more about what is available inside the standard library.
You are getting double free or corruption because first destructor is for object q in this case the memory allocated by new will be free.Next time when detructor will be called for object t at that time the memory is already free (done for q) hence when in destructor delete[] myArray; will execute it will throw double free or corruption.
The reason is that both object sharing the same memory so define \copy, assignment, and equal operator as mentioned in above answer.
You need to define a copy constructor, assignment, operator.
class Test {
Test(const Test &that); //Copy constructor
Test& operator= (const Test &rhs); //assignment operator
}
Your copy that is pushed on the queue is pointing to the same memory your original is. When the first is destructed, it deletes the memory. The second destructs and tries to delete the same memory.
You can also try to check null before delete such that
if(myArray) { delete[] myArray; myArray = NULL; }
or you can define all delete operations ina safe manner like this:
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p) { delete (p); (p) = NULL; } }
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p) = NULL; } }
#endif
and then use
SAFE_DELETE_ARRAY(myArray);
Um, shouldn't the destructor be calling delete, rather than delete[]?

Reason for C++ Destructor error when using this pointer?

I have been working on a code in which I have a lot of classes. I am allocating memory to different arrays of objects in constructor. However I had a strange error while I thought everything was ok. for an example lets say I have a class named Points and it has a double array of points called data.
Okay I am posting all of the code now:
class Points
{
double *data;
Points::Points()
{
data = new double [C_NUMBER_OF_POINTS];
}
Points::~Points()
{
delete [] this->data;
}
};
After debugging I found out that the error was with the this pointer, which I do not know why it is? The destructor is called to delete data, while the object is being destroyed, but it is still in memory. My question is why is it like this?
The error I was getting is basically due to mishandling of memory
Unhandled exception at 0x778f15de in HandTracker.exe: 0x00000000:
The operation completed successfully.
Blockquote
The error is fixed if I remove this pointer meaning if I use the following destructor
Points::~Points()
{
delete []data;
}
My question is not exactly about how to handle memory leaks, it's about this specific problem related with this pointer. What is the mechanism behind this pointer which makes it give this error?
Most likely, somewhere in your code you copied an instance of Points or constructed one from a reference to another. This created two instances of your class with the same data pointer. When the first one was destroyed, it destroyed the object that both instances had pointers to. When the second one was accessed or destroyed, it caused the problem, since the object was already gone.
The best fix is to avoid having a destructor by using well-tested classes that have their own destructors. For example, std::array (or std::vector) in this case. This will make everything "magically work" because these classes already have proper destructors, copy constructors, and copy assignment operators.
Otherwise, make sure you have correct copy constructor and copy assignment operators because the defaults (memberwise copy/duplicate) won't work in your case. See James McNellis' comment about the rule of three.
Try this:
Points::Points(const Points &a)
{
data = new double[C_NUMBER_OF_POINTS];
for (int i = 0; i < C_NUMBER_OF_POINTS; ++i)
data[i] = a.data[i];
}
Points& operator=(const Points& a)
{ // The key is that this overrides the catastrophic default -- data=a.data;
for (int i = 0; i < C_NUMBER_OF_POINTS; ++i)
data[i] = a.data[i];
return *this;
}