memory allocation and copy constructor on struct - c++

I'm just trying this out of curiosity. I have a struct with a constructor and a copy constructor and trying to initialize the struct using the copy constructor in the main, while at the same time within the main, implementing memory allocation to the pointer to a struct. Copy construct initialization works alright, but when I try to free it before the main return, it causes an assertion error in the heap.
#include <stdio.h>
#include <malloc.h>
typedef struct tagInfo
{
int iX;
int iY;
tagInfo() {};
tagInfo(int x, int y)
: iX(x), iY(y) {};
~tagInfo() {};
}INFO;
int main (void)
{
INFO* pInfo = (INFO*)malloc(sizeof(INFO));
pInfo = &INFO(10, 10);
free(pInfo);
return 0;
}
How can I safely free the above pointer without causing assertion errors?

malloc and free should not be used in C++, as they do not deal with construction/destruction of objects.
In modern C++ you should use std::unique_ptr if you want to model unique ownership, or std::shared_ptr if you want to model shared ownership - these are called "smart pointers" and provide a safe way of managing dynamic memory that automatically deals with deallocation/destruction. Example:
int main (void)
{
auto pInfo = std::make_unique<INFO>(10, 10);
return 0;
}
If you really want to go down the road of manual memory management, you must use new (for allocation+construction) and delete (for deallocation+destruction). Example:
int main (void)
{
INFO* pInfo = new INFO(10, 10);
delete pInfo;
return 0;
}

I think the basic misunderstanding is that a copy constructor does not copy the contents of one object into an (already existing) other object of the same type, but rather generates a new object, which is initialized based on the contents of the object to be copied from.
In your code, you reserve memory for an object of type INFO using malloc and let pInfo point to that memory.
Next, with pInfo = &INFO(10, 10) you instantiate a new object of type INFO on the stack (not on the heap), and let pInfo point to the memory address of this object (which is on the stack!). BTW, you loose the reference to your malloc-ed memory, as pointer pInfo does not point to the malloc-ed address any more, but on the new object.
free(pInfo) is critical, as you free a memory address which has not been allocated with malloc before.
Actually, you should do the following:
INFO* pInfo = new INFO(10, 10);
...
delete pInfo;

In general, you can do that with placement new, but it is highly discouraged:
// allocate
void* pInfoMem = malloc(sizeof(INFO));
// construct
INFO* pInfo = new(pInfoMem) INFO(10, 10);
// destruct
pInfo->INFO::~INFO();
// free
free(pInfoMem);
But then you need to manually call the destructor before the freeing.
It is much easier to just do (as other answers mention):
INFO* pInfo = new INFO(10, 10);
delete pInfo;

Related

C++ , how come I do not get the value "123456"

I am trying to print out value 123456, but it gives me the garbage value. How can I fix it? And Can you please explain why it gives the wrong value?
#include <stdio.h>
#include <stdlib.h>
struct MyInfo
{
private:
int private_key = 123456;
public:
int setkey(int value)
{
private_key = value;
}
int GetScore()
{
return private_key;
}
};
void main()
{
MyInfo* pMyInfo;
pMyInfo = (MyInfo*)malloc(sizeof(MyInfo));
printf("%d\n", pMyInfo->GetScore());
free(pMyInfo);
}
Don't use malloc/free but rather pMyInfo = new MyInfo() and delete pMyInfo. Only new will call the constructor which initializes the value; only delete will call the destructor.
Regarding the comment, what is meant is, you can also have it on the stack, i.e. MyInfo pMyInfo;, i.e. not a pointer. That will automatically call the constructor and when it goes out of scope, the destructor.
int private_key = 123456;
This really is just a camouflaged constructor initialization which means it's the same as:
MyInfo() : private_key(123456) {}
Since malloc and friends are inherited from C and C has no classes (and thus no special member functions) whatsoever malloc and friends won't call these necessary special member functions to set up your object. The C++ equivalent new does however which is why you should always use new over malloc and delete over free.
But wait, there's more...
Actually, you shouldn't ever use new either, there are always better alternatives than using raw dynamic allocation. If you really need dynamic memory allocation then use std::unique_ptr or for multiple objects std::vector but most of the time you don't even need these ( there are tons of posts on here that explain when dynamic allocation is a must, for all the other cases just use storage with automatic lifetime) all you need in this case is a local object:
MyInfo myInfo;
printf("%d\n", myInfo.GetScore());
See how your code just got shorter, easier to maintain and cleaner to achieve the same?
When you declare a pointer of type MyInfo, it does not mean that the object it points to will actually be your struct, it just assumes it will be.
When you do malloc(sizeof(MyInfo)), you simply allocate memory of the size which your struct might take, it does not create an object. Hence, when you try to do GetScore(), it accesses memory location which it assumes contains your private_key, but instead it simply contains garbage.
Don't mix C and C++
You should avoid malloc/alloc etc in C++ and opt for new operator if you want to work with dynamically allocated objects.
Add a constructor to initialize the value
private;
int private_key;
public:
MyInfo () {
private_key = 123456;
}
And implement the main like
// without pointer
void main () {
MyInfo myinfo;
printf("%d\n", myinfo.GetScore());
}
// with pointer
void main () {
MyInfo *myinfo = new MyInfo();
printf("%d\n", myinfo->GetScore());
}
Just for reference, it is possible to initialize an object in raw storage, but it would be overkill and rather stupid for this use case. As malloc only allocate raw memory and does not construct an object, you could use a placement new to build the object in a second time:
int main() // I can't stand void main
{
MyInfo* pMyInfo;
pMyInfo = (MyInfo*)malloc(sizeof(MyInfo)); // only allocate raw memory
new((void *) pMyInfo) MyInfo; // construct the object
std::cout << pMyInfo->GetScore() << std::endl; // no reason for C printf here
pMyInfo->~MyInfo(); // placement new requires explicit destructor call if not trivial
free(pMyInfo);
return 0;
}
DO NOT DO THAT for such a simple case. Placement new should only be used in very special cases where the allocation is not trivial, for example when you use share memory. But here the correct way is to simply use an automatic object:
int main() // I can't stand void main
{
MyInfo pMyInfo;
std::cout << pMyInfo.GetScore() << std::endl;
return 0;
}

Where should I put delete statements in my code to remove the memory leak?

There is a memory leak that I see in Valgrind in my C++ program. I'm wondering where I should place delete statements to remote it. Thank you.
#include <iostream>
using namespace std;
void showFloatArray(float f1[10]) {
for (int i=0; i < 10; i++)
cout << " " << f1[i];
cout << endl;
}
float *getFloatArrayOne() {
float *floatArray = new float[10];
for (int i=0; i < 10; i++)
floatArray[i] = (float) i;
return(floatArray);
}
float *getFloatArrayTwo() {
float myFloatArray[10];
float *floatArray = myFloatArray;
for (int i=0; i < 10; i++)
floatArray[i] = (float) i;
return(floatArray);
}
int main()
{
float *f1 = getFloatArrayOne();
float *f2 = getFloatArrayTwo();
showFloatArray(f1);
showFloatArray(f2);
}
Anytime you create a pointer with new then you have to make sure you call delete on that pointer before the program ends.
For example:
int main()
{
Object * obj = new Object;
return 0; //leaky program!
}
int main()
{
Object * obj = new Object;
delete obj;
return 0; //non-leaky program!
}
Quick re-write
Better to get caller to make allocations. Caller then knows to allocate and de-allocate. If your function (eg a library) allocates, then caller might be in doubt about whether objects must be de-allocated.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// remove fixed size restriction on function
void print_array(float* f, size_t size) {
for (size_t i=0; i < size; i++)
cout << " " << f[i];
cout << endl;
}
// pass in array
float* getFloatArrayOne(float f[], size_t size) {
for (size_t i=0; i < size; i++)
f[i] = (float)i;
return f;
}
// pass in ptr - caller responsible for allocation and de-allocating
float *getFloatArrayTwo(float* f, size_t size) {
for (size_t i=0; i < size; i++)
*(f+i) = (float)i; // dereference pointer + offset method
return f;
}
// You can use any algorithm you like to generate numbers
struct myincrementer {
myincrementer(float startval) : n_(startval) {}
float operator()() { return ++n_; } // change to n_++ to start printing first value
float n_;
};
int main()
{
const int size = 10;
float* floatArray = new float[size]();
float *f1 = getFloatArrayOne(floatArray, size);
float myFloatArray[size] = {0};
float *f2 = getFloatArrayTwo(myFloatArray, size);
print_array(f1, size);
print_array(f2, size);
delete [] floatArray; // note [] form
// More advanced approach
vector<float> vec;
myincrementer myi(0.0);
generate_n(back_inserter(vec), 10, myi);
std::copy(vec.begin(), vec.end(), std::ostream_iterator<float>(std::cout, " "));
}
'Modern' C++ typically avoids leaks by not using new and delete directly, instead delegating the management of resources like memory to objects that handle them internally.
However since this is homework it seems worthwhile to learn not just good practices which eliminate problems, but the technical details of what a leak is and the formal requirements to avoid a leak, independent of any particular method for effectively carrying out those requirements.
So here it is: A memory leak occurs when a pointer value is returned by a successful call to an allocation function and no subsequent call to the correct deallocation function is made using the value returned by the allocation function. That is, a leak occurs when you allocate memory and then fail to deallocate it.
Allocations by malloc() must be deallocated with free(). Allocations by new must be deallocated with delete. Allocations by new[] must be deallocated with delete[].
int *x = malloc(sizeof(int)); // C code
if (x) {
// allocation succeeded, you can use the resource and you should free() it
// ... use
free(x);
}
int *y = new int;
delete y;
int *z = new int[10];
delete [] z;
In Practice
So fixing or avoiding memory leaks requires 'merely' that your program call the deallocation function for every successful allocation. The challenge however, is that this is difficult to do in an arbitrary or ad-hoc manner. In order to avoid leaks in practice you need to establish patterns of allocation and deallocation that can be easily managed and verified.
So here are some pointers to get you started on learning about the practicalities of resource management:
The basic practice for managing resource across many languages is to define "ownership semantics" for specific resources. You define rules for determining what part of the program is responsible for any particular allocated resource, and rules for how responsibility for a particular resource may be handed off from one part of the program to another.
Typically ownership semantics are defined such that the part of a program that allocates a resource is responsible for it. That may seem obvious, but there are alternatives. E.g. a program could designate a single entity that takes responsibility for cleaning up everything, and then the rest of the program just allocates at will and has nothing to do with clean-up. But more commonly whatever allocates a resource takes responsibility for it.
For example a function that allocates some dynamic memory to perform its task also frees that memory when its done:
void foo(int n) {
int *arr = malloc(n * sizeof(int));
// ...
free(arr)
}
Another way to 'take responsibility' for an allocated resource is to be explicit about about requirements for resource management when resources are passed off. For example a function which needs to allocate memory and pass that memory back to the caller may specify "callers of foo() must call free_foo(foo_results) when the foo results are no longer needed."
foo_t *foo() {
foo_t *f = malloc(sizeof(foo_t));
// ...
return f;
}
void free_foo(foo_t *f) {
free(f);
}
Exceptions
For correct resource management whatever rules of ownership semantics have been designed must be followed in all circumstances. There's one language feature supported by C++ that has historically given some people trouble, making them think they'd correctly handled resource management responsibilities when in fact they hadn't. This feature is exceptions.
I won't go into details about exceptions, but it suffices to say that they are the reason that code such as:
doSomething();
cleanup();
is incorrect. And once you learn the idiomatic C++ way to manage resources it should be absolutely obvious that the above is wrong, without you even needing to know what doSomething() does. (One common criticism of exceptions is that they require you to know if doSomething() might throw an exception in order to know how to do the cleanup, which could require manually examining a huge amount of code. But since one can do the cleanup correctly without knowing if doSomething() throws, that criticism is incorrect.)
C++
In C++ a specific practice for managing resources has been developed, called RAII, for Resource Acquisition Is Initialization. It's reliable and easy to use, and correctly handles circumstances such as exceptions. Under RAII a resource is represented as an object, and the correct ownership semantics are encoded into the object's special functions: its destructor, copy/move constructors, and copy and move assignment operators.
Thus you acquire a resource by initializing an object of the right type and you access the resource through that object. If the resource can be copied or moved then you can copy or move the object. If the resource is fundamentally not copyable or moveable then the object is non-copyable or non-moveable, and trying to copy or move it will produce a compiler error.
Some resource managing, RAII types in the C++ standard library are:
std::array: a template class that manages a static, in-place memory buffer, presented as an array of objects
std::vector: a template class that manages dynamic memory, presented as a resizable array of objects.
std::string: a template class that manages static and/or dynamic memory, presented as a resizable array of char.
std::shared_ptr: a template class that implements reference counting ownership semantics. By default the resource is a dynamically allocated object, but this can be configured.
std::unique_ptr: a template class that implements unique ownership semantics. By default the resource is a dynamically allocated object or array, but this can be configured.
For more info on resource management in C++ you can visit http://exceptionsafecode.com/
You should probably just delete f1, as the main function terminates. The first one is allocated on the heap dynamically and it remains allocated though-out execution, and it needs to be deleted. As for the second one, you declare it statically (on the stack), and when the function getFloatArrayTwo() terminates, it deallocates already the vector, deleting it again my result a runtime double delete error. After showFloatArray(f2); you should put delete f1, and the leaks should dissapear.
Hope this to be of help.

Using a Constructor through pointer

I have a problem.
The compiler keeps warning me for invalid use of the constructor.
All i wanted to do is to create a new course in the class. whats wrong?
int StArray::addCS_Course(int id, int CourseNum, char* CourseName,int HwNum, float HwWeigh, bool Takef, char* BookName){
int i;
CS_Course* course;
if ((CourseNum<0)||(HwNum<0)||(HwWeigh<0)||(HwWeigh>1))
return 0;
for (i=0;i<StudentNum_;i++){
if (Arr_[i]->getID()==id) {
course=(CS_Course*)malloc(sizeof(CS_Course*));
if (course==NULL) {
fprintf(stderr,"Malloc failed\n");
exit(0);
}
course->CS_Course::CS_Course(CourseNum,CourseName,HwNum,HwWeigh,Takef, BookName);
if (Arr_[i]->addCS_Course(course)==1)
return 1;
else
{
free(course);
return 0;
}
}
}
return 0;
}
To create a new object in C++, you don't do this:
course = (CS_Course*) malloc(...);
course->CS_Course::CS_Course(...);
you do this:
course = new CS_Course(...);
That code looks after both allocating memory and calling the constructor.
You then delete your object with delete course; rather than free(course);
(But as juanchopanza points out in the comments, it's considered bad form to create objects on the heap in C style like this - you should prefer to use standard library containers and avoid the use of new. That's a whole nother discussion - you might want to read a tutorial on modern C++.)
Edit by #RemyLebeau: If you need to construct an object in existing memory, use placement new instead:
buffer = malloc(...);
course = new (buffer) CS_Course(...);
But then you have to call the destructor manually:
course->~CS_Course();
free(buffer);
malloc(sizeof(CS_Course*)) allocates enough space for a pointer to a CS_Course, not a CS_Course itself. If malloc were the right way to dynamically allocate memory for an object, you would need to call it like this:
malloc(sizeof(CS_Course));
However, malloc isn't the right way to do this; in C++, you use new to dynamically allocate memory for objects:
course = new CS_Course; //Use the default constructor
or
//Use constructor with 2 parameters
course = new CS_Course(constructor_param1, constructor_param2);
Of course, if you don't need a pointer, you can (and should) create a CS_Course object like this (generally referred to as allocating on the stack):
CS_Course course; //default constructor
//constructor with 2 parameters
CS_Course course2(constructor_param1, constructor_param2);

no need to delete struct memory in vector<StructA*>?

i saw some code like below, but i didn't see any delete statement, is there any memory leak problem?
struct RStatus
{
int fid;
int status;
};
void Foo()
{
vector<RStatus*> rsVec;
RStatus* rs = null;
rs = new RStatus(); // memory allocated here!
rs->fid = 0
rs->status = 0;
rsVec.push_back(rs);
}
If you use vector<RStatus*>, then you have to use delete, otherwise you will have a memory leak.
However, if you use vector<RStatus>, then you don't have to use delete — this is recommended1.
1. If you want to use pointers, then the recommendation is that you should be using smart pointers such as std::unique_ptr, or std::shared_ptr.
Yes, you should free your memory allocated :
struct RStatus
{
int fid;
int status;
};
void Foo()
{
vector<RStatus*> rsVec;
RStatus* rs = null;
rs = new RStatus(); // memory allocated here!
rs->fid = 0
rs->status = 0;
rsVec.push_back(rs);
// free :
unsigned int size = rsVec.size();
for (unsigned int i = 0; i < size; i++ )
delete rsVec[i]; // delete because you used new
}
If you don't do that, all the memory will never be released at the vector destruction.
I would suggest you to use std::vector<RStatus> instead of std::vector<RStatus*>.
You may also used smart ptr. You can found some documentation about it here : http://www.cplusplus.com/reference/memory/shared_ptr/
EDIT: As suggested in comments, if an exception is thrown at rsVec.push_back(rs), the memory allocated will be lost, that's why smart pointers would be a better solution. Or again, use std::vector<RStatus> instead.
Yes, there is a memory leak: the pointer to the created structure is lost after the vector is destroyed, and the memory is never released.
Unless someone performs a delete for each element of rsVec before clearing or destroying the vector.
Yes, that code leaks the RStatus.
It also does nothing else: possibly the real code's vector gets passed to some function that takes posession of the vector's contents.
Tracking down memory leaks is generally not a local problem: every use of that pointer has to, in theory, be examine to figure out if it leaks. Techniques like 'if I allocate it, delete it' and RAII (including smart pointers) attempt to make it more local, so you can tell from an incomplete program if there is a leak.
use boost::shared_ptr if you don't want to bother yourself with a deletion of allocated objects.
http://www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm
struct RStatus
{
int fid;
int status;
};
void Foo()
{
vector<shared_ptr<RStatus> > rsVec;
shared_ptr<RStatus> rs = shared_ptr<RStatus>(); // empty shared_ptr
rs.reset(new RStatus()); // memory allocated here!
rs->fid = 0
rs->status = 0;
rsVec.push_back(rs); // shared_ptr is copied
}// vector is destroyed and shared_ptrs also
be careful however not to mixed up things using both shared_ptr and ordinary, raw pointers to avoid situation when shared_ptr tries to delete object which is already deleted

allocate memory and before delete the allocation define NULL

I would like to ask if I's correct the following :
MyClass *obj = new MyClass();//allocate memory
obj.Variab="HELLO";
obj=NULL;
delete obj; //free memory
Is the memory allocated for obj deleted after the last two sentences? Appreciate.THX
I would like to mention that I am working in c++ /Ubuntu. G++ is the compiler
EDIT:
What if I have?
int i=0;
list<string>l;
while (i<100)
{
MyClass *obj = new MyClass();//allocate memory
obj->Variab="HELLO";
//add the obj.valie in a list
l.push_back(obj);
i=i+1;
delete obj; //free memory
}
it is ok?
no, you should use delete before assigning to NULL
delete obj; //free memory
obj=NULL;
this is becasue the actual parameter to delete is the address of the allocated memory, but if you assign NULL before delete is used, you are actually passing NULL to delete, and nothing will happen, and you will get yourself a memory leak.
your edit question:
this code will not compile, as obj is not defined outside the while scope, in any case, also, l is a list<string> and you are trying to insert MyClass* types,this will result in another compilation error. also, you should use obj->Variab and not obj.Variab, since obj is a pointer.
EDIT to EDIT:
well, you still got a compilation error, since obj is not defined when you are trying to delete it. try this:
#include <iostream>
#include <list>
using namespace std;
class MyClass {
public:
string Variab;
};
void myfunction (const string& s) {
cout << " " << s;
}
int main()
{
int i=0;
list<string>l;
while (i<100) {
MyClass *obj = new MyClass();//allocate memory
obj->Variab="HELLO";
l.push_back(obj->Variab);
i=i+1;
delete obj; //free memory
}
for_each (l.begin(), l.end(), myfunction);
}
This not correct:
obj = NULL; // don't do that!
delete obj;
When you assign NULL to obj, you're losing the address it contained before, leaking the memory. When you then delete obj, you are deleting NULL, which is well-defined - as doing nothing.
As others have said,
delete obj;
obj = NULL;
is the common pattern to do that.
However, I consider it an anti-pattern.
Whenever you are tempted to assign NULL to a pointer after deleting its content, ask yourself: Why is this pointer still in scope? Are you sure you still need it?
It's much better to simply let a pointer fall out of scope once it's done.
Whenever you are doing
resource r = acquire();
use(r);
free(r);
(with memory/dynamically allocated objects being the most common resource), alarm bells should go off. What if use(r) fails with an exception?
Never use naked, dumb pointers. Better read about RAII and smart pointers.
This would leak, delete will not clean up what you allocated with new. Change the order:
delete obj;
obj = NULL; // I would avoid this.
Setting obj to null does not free the memory you allocated. The memory becomes no longer assigned to a variable but is still reserved, and results in a memory leak. Calling delete on a null pointer will have no effect. After the memory has been freed, the pointer becomes invalid and it is good practice to assign it to null. You need to switch the order of the last 2 statements:
delete obj; //free memory first
obj=NULL; //Set pointer to null for safety
You have to delete the very same address as was returned by new - so you have to first delete, then set to null.
Setting pointer to null doesn't affect allocation - you just overwrite the address stored in the pointer and can't access the object anymore (which implies you can't delete the object and have it leaked).