A union is a user-defined data or class type that, at any given time, contains only one object from its list of members. Suppose all the possible candidate members are needed to be allocated dynamically. For Eg.
// Union Destructor
#include <string>
using namespace std;
union Person
{
private:
char* szName;
char* szJobTitle;
public:
Person() : szName (nullptr), szJobTitle (nullptr) {}
Person (const string& strName, const string& strJob)
{
szName = new char[strName.size()];
strcpy (szName, strName.c_str());
szJobTitle = new char [strJob.size()];
strcpy (szJobTitle, strJob.c_str()); // obvious, both fields points at same location i.e. szJobTitle
}
~Person() // Visual Studio 2010 shows that both szName and szJobTitle
{ // points to same location.
if (szName) {
delete[] szName; // Program crashes here.
szName = nullptr; // to avoid deleting already deleted location(!)
}
if (szJobTitle)
delete[] szJobTitle;
}
};
int main()
{
Person you ("your_name", "your_jobTitle");
return 0;
}
Above program get crashed at 1st delete statement in ~Person (at moment when szName contains valid memory location, WHY?).
What will be the correct implementation for the destructor?
Same way, how to destruct a class object, if my class contains an union member (how to wrtie destructor for class including a Union)?
You can only use one member of the union at a time because they share the same memory. In the constructor, however, you initialize both members, which overwrites each other, and then in the destructor you end up releasing it two times. You're trying to use it as if it were a struct (based on the names of the fields you need to use a struct).
Nevertheless, if you need a union then you probably need a struct as a kind of envelope which has some id representing the member being used, as well as a constructor and a destructor that handles the resources.
Also - your arrays are too small. size() returns the number of characters, but if you use char* as your string type then you need space for the null-character (\0) to handle termination.
If you need unions, try using Boost.Variant. It is a lot easier to use than normal unions.
You're using delete when you should use delete [], because you have used new [], not new.
Change these:
delete szName;
delete szJobTitle;
to these:
delete [] szName;
delete [] szJobTitle;
By the way, the if condition in the destructor is pointless. I mean, if a pointer is nullptr, then it is safe to write delete ptr;, that is,
A *ptr = nullptr;
delete ptr; //Okay! No need to ensure ptr is non-null
Apart from that, you're violating rule of three (or five, in C++11):
What is The Rule of Three?
Rule-of-Three becomes Rule-of-Five with C++11?
Implement them.
You don't respect that new-delete pairing: new pairs with delete, new[] pairs with delete[]. You're doing new[], but calling delete; that's incompatible.
As a side note, the constructor has a memory leak: the memory assigned to szName is never freed once that pointer is overwritten by the assignment to szJobTitle).
And as this is C++, you should generally be using std::string instead of char* for strings.
Above program get crashed at 1st delete statement in ~Person (at moment when szName contains valid memory location, WHY?).
I don't have a compiler with me (or time to compile your code) but (apart from the problems addressed by Nawaz) I would guess it's because you treat the union members as class members. In your union, szName and szJobTitle should be looked like two variables with the same address:
Person (const string& strName, const string& strJob)
{
szName = new char[strName.size()];
strcpy (szName, strName.c_str());
szJobTitle = new char [strJob.size()]; // this creates memory leak (1)
strcpy (szJobTitle, strJob.c_str());
}
You get a memory leak because you allocate new memory and place it in szJobTitle. &szJobTitle uses the same memory location as &szName, so with the assignment in line (1) you loose the address allocated in szName. If szName and szJobTitle were of different types (with non-matching memory footprints), setting szJobTitle would also corrupt (or only partially overwrite szTitle).
What will be the correct implementation for the destructor?
I think you do not have enough details for implementing the destructor. Look into the concept of discriminated unions in C++ to see how to implement this correctly. Normally your union members should manage their own memory (use std::string, not char*) and then your destructor would only delete what was allocated (but you will have to call it explicitly).
Same way, how to destruct a class object, if my class contains an union member (how to wrtie destructor for class including a Union)?
Again, look at discriminated unions. It is basically the association of a union and an enum, where the enum maps to the members of the union and is set to specify which of the members of the union was set.
Related
I have tried some interesting code(at least for me !). Here it is.
#include <iostream>
struct myStruct{
int one;
/*Destructor: Program crashes if the below code uncommented*/
/*
~myStruct(){
std::cout<<"des\n";
}
*/
};
struct finalStruct {
int noOfChars;
int noOfStructs;
union {
myStruct *structPtr;
char *charPtr;
}U;
};
int main(){
finalStruct obj;
obj.noOfChars = 2;
obj.noOfStructs = 1;
int bytesToAllocate = sizeof(char)*obj.noOfChars
+ sizeof(myStruct)*obj.noOfStructs;
obj.U.charPtr = new char[bytesToAllocate];
/*Now both the pointers charPtr and structPtr points to same location*/
delete []obj.U.structPtr;
}
I have allocated memory to charPtr and deleted with structPtr. It is crashing when I add a destructor to myStruct otherwise no issues.
What exactly happens here. As I know delete[] will call the destructor as many times as number given in new[]. Why it is not crashing when there is no destructor in myStruct?
First off, storing one member of a union and then reading another in the way you're doing it is Undefined Behaviour, plain and simple. It's just wrong and anything could happen.
That aside, it's quite likely the type pun you're attempting with the union actually works (but remember it's not guaranteed). If that's the case, the following happens:
You allocate an array of bytesToAllocate objects of type char and store the address in the unionised pointer.
Then, you call delete[] on the unionised pointer typed as myStruct*. Which means that it assumes it's an array of myStruct objects, and it will invoke the destructor on each of these objects. However, the array does not contain any myStruct objects, it contains char objects. In fact, the size in bytes of the array is not even a multiple of the size of myStruct! The delete implementation must be thoroughly confused. It probably interprets the first sizeof(myStruct) bytes as one myStruct object and calls the destructor in those bytes. Then, there's less than sizeof(myStruct) bytes left, but there are still some left, so the destructor is called on those incomplete bytes, reaches beyond the array, and hilarity ensues.
Of course, since this is just UB, my guess at the behaviour above could be way off. Plain and simple, you've confused it, so it acts confused.
delete makes two things, call destructor and deallocate memory.
You allocate data for one type, but delete if faking another type.
You shouldn't do it. There are many things one could do in C/C++, take a look at IOCCC for more inspirations :-)
A struct in C++ without any function and having only plain old data is itself a POD. It never calls a constructor/destructor when created/deleted.
Even not standard c-tors/d-tors. Just for performance reasons.
A Struct having (EDIT) user-defined copy-assignment operator, virtual function or d-tor is internally a little bit more complicated. It has a table of member function pointers.
If you allocate the memory block with chars, this table is not initialized. When you try to delete this memory block using a not POD-type, it first calls the destructor. And as the destructor function pointer is not initialized, it calls any memory block in your memory space, thinking it was the function. That's why it crashes.
It works because myStruct does not have a destructor. [Edit: I now see that you tried that, and it does crash. I would find the question interesting why it crashes with that dtor, since the dtor does not access any memory of the object.]
As others said, the second function of free[] besides potentially calling the elements' dtors (which doesn't happen here, as described) is to free the memory.
That works perfectly in your implementation because typically free store implementations just allocate a block of memory for that purpose whose size is kept in a book keeping location in that very memory. The size (once allocated) is type independent, i.e. is not derived from the pointer type on free. Cf. How does delete[] "know" the size of the operand array?. The malloc like, type agnostic allocator returns the chunk of memory and is happy.
Note that, of course, what you do is bogous and don't do that at home and don't publish it and make ppl sign non liability disagreements and don't use it in nuclear facilities and always return int from main().
the problem is that obj.U.structPtr points to a struct, which can have a constructor and destructor.
delete also requires the correct type, otherwise it cannot call the destructor.
So it is illegal to create a char array with new and delete it as an struct pointer.
It would be okay if you use malloc and free. This won't call the constructor and destructor.
I'm using a C library (libwebsockets) which allows some user-data for each client. The library owns this memory, passes it as a void*, and my code reinterpret_cast's it to my user-data type.
I'm trying to add a std::string field to this class and am now seeing segfaults. Calling functions on this class causes errors, which is fair enough as it's likely backed by uninitialised memory.
How can I initialise that memory> I've tried assigning (the assignment operator segfaults) and calling various functions such as clear. I'm guessing there's a C++ mechanism for this.
Furthermore, how can the destructor be called when the string is no longer needed?
Assuming that you have a type something like this:
class MyType
{
std::string foo;
std::string bar;
};
And assuming that the void * points to an uninitialized allocation of at least sizeof(MyType) bytes, then you can construct it (and all contained objects) using placement new syntax:
void init_callback(void * ptr) {
new (ptr) MyType();
}
Similarly, you can destruct your type (which will destruct all contained objects) by calling the destructor directly.
void destroy_callback(void * ptr) {
MyType * mine = reinterpret_cast<MyType *>(ptr);
mine->~MyType();
}
Generally you don't call destructors directly, but you have to because you can't safely delete the pointer. The rule "every new should have one delete" has an analog in this situation: "every placement-new should have one explicit call to the destructor."
You can use placement-new to create an object in the provided memory:
std::string * s = new(memory) std::string;
and call the destructor to destroy it before reusing or releasing the memory:
s->std::string::~string();
If you find that a bit of a mouthful, then using std::string; will reduce it to s->~string();
I'm new to this website, and to the programming world. So, please be patient with me :)
I read about the rule of three, and I understood how the Copy Constructor and the Assignment operator work.
So I understood that, the default ones, provided by C++, provide a shallow-copy (or memberwise) of the objects.
My question is ... if the class has a member pointer (which points to dynamic allocated memory), the default Assignment Operator, will only copy the address held in the pointer from the original object to the pointer of the object is being assigned to. But won't this create a memory leak?
For example, the followind code:
class GCharacter //Game Character
{
private:
std::string name;
int capacity; //the capacity of our tool array
int used; //the nr of elements that we've actually used in that tool array
std::string* toolHolder; //string pointer that will be able to reference our ToolArray;
public:
static const int DEFAULT_CAPACITY = 5;
//Constructor
GCharacter(std::string n = "John", int cap = DEFAULT_CAPACITY)
:name(n), capacity(cap), used(0), toolHolder(new string[cap])
{
}
}
int main()
{ GCharacter gc1("BoB", 5);
GCharacter gc2("Terry", 5);
gc2 = gc1;
GCharacter gc3 = gc1;
return 0;
}
So, in this code, when gc1 is created, gc1.toolHolder holds the address of some dynamic allocated memory of 5 strings. Let's say, address 125. After this, gc2 is created and dynamic allocates memory for 5 strings, and let's say gc2.toolHolder holds the address 135.
The next line of code, calls the default assignment operator, and provides a shallow-copy from every member of gc1 to gc2. This means that now the pointer gc2.toolHolder also holds the address 125, and we no longer can access the memory at address 135. So the default assignment operator, in situations like these, creates memory leaks? ... or I understood something wrong??
Also, another question, in the case of the default Copy Constructor, because it is called only on objects that don't already exist, it means that gc3.toolHolder won't get the chance to allocate new memory, let's say, at address 145? It will just receive the address stored in gc1.toolHolder?
To try to be more specific... what I'm asking is if it's the same case as above, except we just have both pointers gc3.toolHolder and gc1.toolHolder, reference the same address 125, without gc3.toolHolder dynamic allocating new memory of 5 strings.
Long story short, when we instantiate a class that has a pointer member variable which points to dynamic allocated memory, will the default assignment operator cause a memory leak? and the default copy constructor share pointers to the same allocated memory?
Thank you for your time!
The memory leak you have is the lack of a destructor which frees the memory allocated with new in the constructor, you need:
~GCharacter() { delete[] toolHolder; }
If you add this, you will see the second problem you have: The default generated copy-ctor and assignment just copy/assign the pointer, hence when you have a copy and both original and copy go out of scope, they will both try to delete the memory. This double-free is of course the much bigger problem than the memory leak as it will most likely corrupt the memory.
That said, you want to add your own copy-ctor and assignment operator and implement it correctly. In this case it means to allocate memory for the copy's toolHolder. Generally, read about the Rule of Five for when to implement which set of methods for your class.
I've been shown that a std::string cannot be inserted into a boost::lockfree::queue.
boost::lockfree::queue is too valuable to abandon, so I think I could use very large, fixed length chars to pass the data according to the requirements (assuming that even satifies since I'm having trouble learning about how to satisfy these requirements), but that will eat up memory if I want large messages.
Does a dynamically-sized text object with a copy constructor, a trivial assignment operator, and a trivial destructor exist? If so, where? If not, please outline how to manifest one.
A dynamically-size type with a trivial copy ctor/dtor is not possible. There are two solutions to your problem, use a fixed sized type, or store pointers in the queue:
boost::lockfree::queue<std::string*> queue(some_size);
// push on via new
queue.push(new std::string("blah"));
// pop and delete
std::string* ptr;
if(queue.pop(ptr))
{
delete ptr;
}
Does a dynamically-sized text object with a copy constructor, a trivial assignment operator, and a trivial destructor exist?
Dynamically sized, no. For something to have a trivial destructor, it requires that the destructor of the object is implicit (or defaulted), and any non-static member objects also have implicit (or defaulted) destructors. Since anything that is dynamically allocated will require a delete [] somewhere along the line in a destructor, you cannot have this constraint satisfied.
To expand upon the above, consider a (very cut down) example of what happens in std::string:
namespace std
{
// Ignoring templates and std::basic_string for simplicity
class string
{
private:
char* internal_;
// Other fields
public:
string(const char* str)
: internal_(new char[strlen(str) + 1])
{ }
};
}
Consider what would happen if we left the destructor as default: it would destroy the stack-allocated char * (that is, the pointer itself, not what it points to). This would cause a memory leak, as we now have allocated space that has no references and hence can never be freed. So we need to declare a destructor:
~string()
{
delete[] internal_;
}
However, by doing this, the destructor becomes user-defined and is therefore non-trivial.
This will be a problem with anything that is dynamically allocated. Note that we cannot fix this by using something like a shared_ptr or a vector<char> as a member variable; even though they may be stack allocated in our class, underneath, they are simply taking care of the memory management for us: somewhere along the line with these, there is a new [] and corresponding delete [], hence they will have non-trivial destructors.
To satisfy this, you'll need to use a stack allocated char array. That means no dynamic allocation, and therefore a fixed size.
I had made a header file with a class named cmysqldb with a lot of pointers.
My problem is now this:
How could i create a destructor that will delete the pointers that may cause potential memory leak?
here is the header code:
#ifndef CMSYQLDB_H
#define CMSYQLDB_H
#include <QMultiMap>
#include <QStringList>
#include "mysql.h"
class cmysqldb
{
public:
cmysqldb::~cmysqldb()
{
const char *text,
MYSQL *connection,
MYSQL_RES *result,
MYSQL_RES *fresult,
MYSQL_FIELD *mfield
}
int query_state;
int numfields;
MYSQL mysql;
MYSQL_ROW row;
MYSQL_ROW fieldrow;
....
};
#endif // CMSYQLDB_H
is this what you mean???
Resources acquired through new should be deallocated using delete and with new[] should be with delete[]. As simple as that to avoid memory leaks. Could be more helpful if you post more specific code.
Destructor bears the same name of the class, except that it has a ~ symbol before it.
cmysqldb :: ~cmysqldb()
{
// deallocate the resources with the above mentioned rule
}
class foo
{
int var ;
int *ptr ;
public:
foo()
{
ptr = new int ;
}
~foo()
{
delete ptr ;
}
};
void bar()
{
foo obj ;
// .....
} // <-- obj goes out of scope and it's destructor is called at this point.
foo class has two member variables var, ptr of type int, int* respectively. So, bytes required to hold an integer in var and pointer(ptr) that can point to an integer's address is automatically allocated. These resources are not allocated by us. So, it's not our responsibility to deallocates these resources. So far so good.
ptr = new int ;
new int acquires resources from the free store that can hold an int and it's address is returned which ptr holds. Now, this acquisition of resource from free store is because of the new operation defined by the user. So, it's the job of the user to return the resources back to the free store. So, the statement in the destructor -
delete ptr ;
Get a book from The Definitive C++ Book Guide and List which can even explain better. Also follow #Michael advice of using smart pointers which manages resources automatically.
In order to delete the pointers, you will need to store them somewhere. It is unclear where you do this (you don't have fields for all the pointer parameters accepted by the constructor), so I won't be able to give you exactly the code to do this, but I will lay out how you can go about doing this.....
To declare the destructor, add the following to your class declaration:
~cmysqldb();
Note that if your class will have any virtual methods, you should instead declare it as:
virtual ~cmysqldb();
And in your source file add:
cmysqldb::~cmysqldb()
{
// contents of your destructor goes here.
}
Now, how exactly you free your resources depends on how they were allocated. If you used some library-specific create function and there is a library-specific free function, then use that. If it was allocated using malloc, then use free; if it was allocated with new, use delete; if it was allocated using new[], then use delete[]. Also, you should use smart pointer classes such as boost::scoped_ptr (std::unique_ptr) or boost::shared_ptr (std::shared_ptr), wherever possible to avoid explicitly managing these resources via new/delete in your constructors / destructors.
One last, very important point... whenever you have a function that accepts a pointer, it is very important that you document the ownership semantics. Is it owned by the caller? Is ownership transferred? Etc.
A memory leak occurs when you acquire dynamic memory using new or new[] & do not deallocate the memory using delete or delete[]`.
Your constructor declaration is of the type:
cmysqldb(const char *text, MYSQL *connection, MYSQL_RES *result,
MYSQL_RES *fresult, MYSQL_FIELD *mfield);
You should keep a track of whatever dynamic memory allocations you are doing in the constructor with new and new[]and you should deallocate all of them with a corresponding delete or delete[].
The best thing to do would be to use smart pointers to store all the pointers to related objects. C++ will automatically call destructors of all sub-objects when the parent object is destroyed.
And if your parent object fails partly constructed, its destructor won't be called. So any pointers already allocated would leak if you design things to be freed in the destructor. However, subobjects destructors get run if the subobject was allocated, so by using smart pointers this partly allocated case is taken care of for you.
For more information, look up RAII (Resource Acquisition Is Initialization).