C++ release allocated char* into string - c++

I have tried to find an answer but couldn't see anything straight forward.
How do I free the allocated memory in the next snippet code:
const char* attStr = strdup(OtherCharStr);
string str(attStr, strlen(attStr));
delete str; //???

C++ uses idiom called RIAA - Resource Acquisition Is Initialization. It means that object lifetime is driven by variable scope.
{
std::string s("foo"); // variable s declaration and string initialization
do_some_stuff(s);
// end of scope of variable s - it is destroyed here
// no need to free(s) or whatever
}
// variable s and the string doesn't exist here, no memory for it is allocated
This applies only for C++ objects that maintain its resources properly (are freeing them in the destructor). Simple pointers doesn't do it - you have to free them yourself:
const char *attStr = strdup(...);
// do something with attStr
free(attStr); // because strdup() documentation says you should free it with free()
Also notice that C++ uses new and delete rather than malloc() and free():
std::string *strPointer = new std::string(...);
// RIAA doesn't work here, because strPointer is just plain pointer,
// so this is the case when you need to use free() or delete
delete strPointer;
I recommend to read something about smart pointers which are deleting the object they point to automatically. I'm getting pretty far from the original question but this topic is important to understand how C++ works.

You need to release attStr not the c++ string that will release its resources alone.
void func()
{
const char* attStr = strdup(OtherCharStr);
string str(attStr, strlen(attStr));
free(attStr);
}//here str will release its own resources
Also you can do
string str = OtherCharStr;
an that's it. Only check what happens with OtherCharStr

Related

Why delete is needed in the definition of the copy-assignment operator?

I am a C++ beginner. And I am doing the exercises in C++ Primer (5th Edition). I found a reference to
Exercise 13.8 from Github (Here), which is shown below.
#include <string>
#include <iostream>
using std::cout;
using std::endl;
class HasPtr {
public:
HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }
HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
HasPtr& operator=(const HasPtr &hp) {
std::string *new_ps = new std::string(*hp.ps);
delete ps; // I don't know why it is needed here?
// But when I delete this line, it also works.
ps = new_ps;
i = hp.i;
return *this;
}
void print() {
cout << *(this->ps) << endl;
cout << this->i << endl;
}
private:
std::string *ps;
int i;
};
int main() {
HasPtr hp1("hello"), hp2("world");
hp1.print();
hp1 = hp2;
cout << "After the assignment:" << endl;
hp1.print();
}
What makes me confusing is the HasPtr& operator=(const HasPtr &hp) function. I don't know why delete ps; is needed here. I thought it was an error, but it worked when I compiled the code. However, it also works when I delete the line of delete ps;. So, I do not know whether delete ps; is needed and what is the advantage if it is reserved.
HasPtr::ps is an heap-allocated std::string pointer.
It is allocated and constructed using new in all HasPtr constructors. Therefore, when HasPtr::ps gets replaced by another heap-allocated pointer, the existing memory has to be released using delete to avoid memory leaks.
Note that, in modern C++, you should almost never use new and delete for managing objects like this. Use smart pointers instead, like std::unique_ptr or std::shared_ptr, which take care of memory management for you, safely and conveniently.
I still suggest getting familiar with new and delete, as an huge amount of existing code makes use of them. cppreference.com is a great place to find detailed information about the language.
As Jan Hudec mentioned in the comments, it is generally pretty silly to store an std::string on the heap - std::string is a wrapper around an heap-allocated character array, which already manages the memory for you.
It's needed to prevent a memory leak: every new must be balanced with a delete.
You allocate memory for ps with a new in the constructors.
When you allocate memory for new_ps and assign this to ps, you need to free the constructor-allocated memory before you lose the old pointer value.
You program will indeed "work" if you omit that line, but it will steadily consume more and more memory, until, eventually there is no more memory left.
Note that you have another memory leak: you need to create a destructor, and call delete ps in it.
As you can see, this is getting unduly complicated. Better still, ditch all this pointer stuff and use a std::string s as the member variable - it takes care of all the memory management for you.
The delete is needed to avoid a memory leak.
The line ps = new_ps; edits the address of ps to point somewhere else.
The memory that ps was previously pointing at still needs to be freed. The effects of removing this line are not instantly visible and the program will still 'work', but you have a memory leak.
Eg.
ps = address 0 with value 'f'; new_ps = address 1 with value 'g'
Now let ps = new_ps;
ps = address 1 with value 'g'; new_ps = address 1 with value 'g'
So address 0 is no longer something we can access, but it's not been freed either
In C++ programming, calling delete on a class object automatically invokes the destructor of the class.
In general practice, destructor holds the code to free up the resources i.e file pointers,deletion of objects created inside the class.This way, when you call delete on an object,the resources it allocated are freed up i.e given back to the system
If these resources are not freed up,the memory allocated for these resources will not be given back to the system.Every time your object gets called,you lose a certain portion of memory and over a period of time you would have lost a major chunk of memory.This is called as memory leak.
Thus when you call delete on an object,you ensure that the resources you acquired are released, provided you have done those operations in destructor.

Object in map corrupted after retrieving from the map

So I've completely edited my question.
I have a map called mTextMap which contains:
typedef std::map<const std::string, Text*> TextMap;
TextMap mTextMap;
And I have the following methods:
void Foo::setUpGame()
{
Text text(1,2,3,4); //create a Text object
mTextMap["MainText"] = &text; //save it in the map!
}
Text& Foo::getText(const std::string name)
{
auto i= mTextMap.find(name);
return *(i->second); //Gets a reference to the Text that is inside the map
}
Now if I use this way:
Foo foo;
foo.setUpGame();
Text& myText = foo.getText("MainText"); // Why is this corrupted?
The object myText is completely corrupted!!
Why is this happening?
The general problem seems to be, that you think that this line:
mTextMap["MainText"] = &text;
stores the text object in the map. IT DOESN'T! It stores a pointer to the object in the map and the text object itself will - as you said yourself - automatically be destructed at the end of the function. So now your pointer points to a non-existing object, which leads to the observed errors.
There are various solutions to your problem, depending on what exactly, you try to achieve and what you are going to do with your class.
One possibility is to use a map of Text objects (instead of pointers):
typedef std::map<const std::string, Text> TextMap;
void Foo::setUpGame()
{
Text text(1, 2, 3, 4); //create a Text object
mTextMap["MainText"] = text; //copy it into the map!
}
or
void Foo::setUpGame()
{
mTextMap.emplace("MainText", Text(1, 2, 3, 4)); //Doesn't require Text to be default constructable
}
Another possibility is to create the text objects on the heap and use smart pointers (e.g. unique_ptr)
typedef std::map<const std::string, std::unique_ptr<Text>> TextMap;
void Foo::setUpGame()
{
mTextMap["MainText"] = std::make_unique<Text>(1,2,3,4); //create object on the heap an store a pointer to it in the map
}
The std::unique_ptr will automatically destroy the text object, as soon as the map gets destroyed.
If you really need to have a map of raw pointers for some reason, you can use "new" as explained by David, but don't forget to delete them when you don't use them anymore - c++ doesn't have a garbage collector (like e.g. java) that would take care of this automatically.
The "text" object is going out of scope as soon as setUpGame completes. At this point, the heap memory is freed up to be overwritten by any new use of the heap. It is essentially a temporary scratchpad of items that only exists within the scope of a function (or within explicit scope operators inside a function).
David G's advice is sound: read more about the difference between stack and heap memory, and also consider the advice to use smart pointers. However, if you want a cheap, dirty fix to your immediate problem, you can try this:
void Foo::setUpGame()
{
static Text text(1,2,3,4); // Note use of "static" keyword
mTextMap["MainText"] = &text; //save it in the map!
}
Whilst I do not advocate the use of static as a shortcut to solving more fundamental architectural memory issues, you can use this as a short-term measure if you're desperate to get things working. Labeling the object as static ensures its lifetime will outlive the scope of the function. But I would not recommend it as a long-term solution to this kind of issue.
When you dynamically allocate memory for your object, it will live as long as you do not explicitly delete it from memory, it is not deleted after you exit the method it was created in, so you can put a pointer to it in a map and it will always be there (just be sure you delete the memory when removing the object from the map).
You can test this with the following simple code, where I declare a new Int in a function, return a pointer to the memory and print it in the other function that received the map (with the pointer in it). It prints correctly, which means the memory was not freed even when out of scope.
#include <iostream>
#include <map>
std::map<std::string, int*> myMap(){
int* test = new int(1);
std::map<std::string, int*> ObjMap;
ObjMap["object"] = test;
return ObjMap;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::map<std::string, int*> mmap = myMap();
std::cout << *mmap["object"] << std::endl;
return 0;
}
So to answer your question, create your object dynamically like this:
Obj* obj = new obj(1,2,3,4);
And it will not be deleted when out of scope. Still, you need to delete the memory yourself unless you use Smart Pointer, like this: delete obj; (when you remove it from the map, to free the memory as it will not be freed automatically).
PS: You should read on how the Stack and Heap works and how Dynamic and Static allocation works (using the stack OR the heap). See this c++ dynamic memory allocation tutorial to have more informations.
Like MikeMB said, using Smart Pointers is easier as you will be sure you deleted the memory, and you will also be sure you never access a deleted memory. See this Stack Overflow topic for smart pointers informations: What is a smart pointer and when should I use one?

Strange this-> behaviour

So i have the following class
class Community
{
private:
char* Name;
char foundationDate[11];
Person* founder;
int maxMembersCount;
int membersCount;
Person* members;
static int communitiesCount;
.....
and i want to implement a copy constructor :
Community::Community(const Community& other)
{
this->Name = new char[strlen(other.Name)+1];
strcpy(this->Name,other.Name);
strcpy(this->foundationDate,other.foundationDate);
this->founder = other.founder;
this->maxMembersCount = other.maxMembersCount;
this->membersCount = other.membersCount;
this->members = new Person[this->maxMembersCount];
this->members = other.members;
communitiesCount++;
}
but this code crashes whenever i say Community A=B;
so for me this code seems legit, but when i start debugging there is the message: this-> "unable to read memory". Please help me if you need more code example please let me know.
Community::Community(const char* name , char foundDate[],Person* founder,int maxMembers) {
this->Name = new char[strlen(name)+1];
strcpy(this->Name,name);
strcpy(this->foundationDate,foundDate);
this->founder = new Person(founder->getName(),founder->getEGN(),founder->getAddress());
this->maxMembersCount = maxMembers;
this->membersCount = 2;
this->members = new Person[this->maxMembersCount];
communitiesCount++;
}
this is the main constructor of the class which works just fine....
There are multiple problems here, any of whichi could be part or all of the problem.
If Name or foundationDate is not null-terminated on the right-hand side, it will run off and copy bad memory.
If founder or members are owned by the object, you will either leak memory if you don't delete them in the destructor, or cause a whole variety of memory-related problems when you shallow-copy and then delete twice, etc.
To fix this, just make your Name and foundationDate std::string, and then make founder and members be owned by value rather than by pointer. If you absolutely have to allocate them on the heap use a smart pointer such as shared_ptr to hold it instead of a bug-prone raw pointer.
First of all, check that other.Name is filled with a pointer to a null-terminated string, that other.foundationDate contains a null-terminated string. That is, you pass good pointers to strlen and strcpy.
If that's true, check that B in the assignment is accessible altogether.
If that's true too, printf everything. And debug where exactly the exception occurs. Or post whole code that is compilable and which reproduces the error.
Also note that here:
this->members = new Person[this->maxMembersCount];
this->members = other.members;
the first assignment does nothing (leaks memory, in fact) while the second double deletes your memory upon object destruction (if you properly delete[] members).

How to create a memory leak in C++?

I was just wondering how you could create a system memory leak using C++. I have done some googling on this but not much came up, I am aware that it is not really feasible to do it in C# as it is managed code but wondered if there was a simple way to do this with C++? I just thought it would be interesting to see how much the system suffers because of code not being written properly. Thanks.
A memory leak occurs when you call new without calling a corresponding delete later. As illustrated in this sample code:
int main() {
// OK
int * p = new int;
delete p;
// Memory leak
int * q = new int;
// no delete
}
Create pointer to object and allocate it on the heap
Don't delete it.
Repeat previous steps
????
PROFIT
int main() {
while(true) new int;
}
There are many kinds of memory leaks:
Allocated memory that is unreleasable because nothing points to it.
These kind of leaks are easy to create in C and C++. They are also pretty easy to prevent, easy to detect, and easy to cure. Because they are easy to detect there are lots of tools, free and commercial, to help find such leaks.
Still-accessible allocated memory that should have been released a long time ago.
These kinds of leaks are much harder to detect, prevent, or cure. Something still points to it, and it will be released eventually -- for example, right before exit(). Technically speaking, this isn't quite a leak, but for all practical purposes it is a leak. Lots of supposedly leak-free applications have such leaks. All you have to do is run a system profile to see some silly application consume ever more memory. These kinds of leaks are easy to create even in managed languages.
Allocated memory that should never have been allocated in the first place.
Example: A user can easily ask Matlab to creating these kinds of leaks. Matlab is also rather aggressive at creating these kinds of leaks. When Matlab gets a failure from malloc it goes into a loop where it waits for a bit and then retries the malloc. Meanwhile, the OS frantically tries to deal with the loss of memory by shuffling chunks of programs from real memory into virtual memory. Eventually everything is in virtual memory -- and everything creeps to a standstill.
Just write an application which allocates "a lot of data" and then blocks until it is killed. Just run this program and leave it running.
class ClassWithLeakedMemory{
private:
char* str;
public:
ClassWithLeakedMemory(){
str = new char[100];
}
~ClassWithLeakedMemory(){
cout<<"We are not freeing the dynamically allocated string memory"<<endl;
}
};
class ClassWithNoLeakedMemory{
private:
char* str;
public:
ClassWithNoLeakedMemory(){
str = new char[100];
}
~ClassWithNoLeakedMemory(){
cout<<"We are freeing the dynamically allocated string memory"<<endl;
delete[] str;
str = null;
}
};
int main() {
//we are creating an automatic object of the ClassWithleakedMemory
//when we will come out of the main, this object will be
//out of scope. hence it will be deleted. so destructor will
//be called. but in the destructor, we have not specifically
//deleted the dynamically allocated string.
//so the stack based pointer object str will be deleted but the memory
//it was pointing to won't be deleted. so we will be left with an
//unreferenced memory. that is memory leak.
ClassWithLeakedMemory objectWithLeakedmemory;
ClassWithNoLeakedMemory objectWithNoLeakedmemory;
return 0;
}
The way the stack based pointer object refers to the dynamically allocated memory in both the classes can be shown pictorially as below:
In C#, just use P/Invoke to allocate a lot of memory, resource handles and keep them around.
You can use unmanaged code just fine in a simple C# harness
When an object that is created using new is no longer referenced, the delete operator has to be applied to it. If not, the memory it occupies will be lost until the program terminates. This is known as a memory leak. Here is an illustration:
#include <vector>
using namespace std;
void memory_leak(int nbr)
{
vector<int> *ptrVector = new vector<int>(nbr);
// some other stuff ...
return;
}
If we return without calling delete on the object (i.e. delete ptrToVector) a memory leak occurs. To avoid this, don't allocate the local object on the memory heap but instead use a stack-allocated variable because these get automatically cleaned up when the functions exits. To allocate the vector on the run-time stack avoid using new (which creates it on the heap) and the pointer.
It's as simple as:⠀⠀⠀
new int;
#include <stdio.h>
void main(){
for(int i = 0; i < 1000; i++)
double* ptr = (double*)malloc(1000000*sizeof(double))
//free(ptr);
ptr = NULL;
}
note : the hashed line of code caused a memory leak while the process allocated it and did't return it back to the OS

How to properly free a std::string from memory

What's the best way to delete an std::string from memory allocated on the heap when I'm done using it? Thanks!
std::string is just a normal class1, so the usual rules apply.
If you allocate std::string objects on the stack, as globals, as class members, ... you don't need to do anything special, when they go out of scope their destructor is called, and it takes care of freeing the memory used for the string automatically.
int MyUselessFunction()
{
std::string mystring="Just a string.";
// ...
return 42;
// no need to do anything, mystring goes out of scope and everything is cleaned up automatically
}
The only case where you have to do something is when you allocate an std::string on the heap using the new operator; in that case, as with any object allocated with new, you have to call delete to free it.
int MyUselessFunction()
{
// for some reason you feel the need to allocate that string on the heap
std::string * mystring= new std::string("Just a string.");
// ...
// deallocate it - notice that in the real world you'd use a smart pointer
delete mystring;
return 42;
}
As implied in the example, in general it's pointless to allocate a std::string on the heap, and, when you need that, still you should encapsulate such pointer in a smart pointer to avoid even risking memory leaks (in case of exceptions, multiple return paths, ...).
Actually std::string is defined as
namespace std
{
typedef std::basic_string<char> string;
};
so it's a synonym for the instantiation of the basic_string template class for characters of type char (this doesn't change anything in the answer, but on SO you must be pedantic even on newbie questions).
std::string foo("since it's on the stack, it will auto delete out of scope");
or:
std::string* foo = new std::string("allocated on the heap needs explicit destruction")
delete foo;
Use delete if it's on the heap, and nothing at all if it's on the stack.
void foo() {
string* myString = new string("heap-allocated objects are deleted on 'delete myString;'");
cout << *myString << endl;
delete myString;
}
or better yet, avoid pointers when possible and use automatic variables:
void foo() {
string myString("stack-allocated string is automatically deleted when myString goes out of scope");
cout << myString << endl;
}
just treat std::string as any basic type.
std::string *str = new std::string("whatever");
///code
delete str;
Maybe your dealing with really freeing the internal string buffer?
For performance reason, most implementation keep the internal buffer allocated, even is the string is "emptied". Additionally: small strings (smaller than sizeof(ptr)) are directly stored in the area that hold pointers. Theses bytes can never be reclaimed during the life of the string.
To free the internals: the classical trick is to use swap within a scope. This force buffer to be really freed (Works also with vector/map/ostream/stringstream etc ...):
string s; // size==0 and capacity==15 as the default proxy of the container (help perf on small string)
s = "Looooooooooooooooooooooooooooooong String"; // size==41 and capacity==47 bytes allocated
s.clear(); // size==0 BUT capacity==47 bytes STILL allocated!!
s = "Looooooooooooooooooooooooooooooong String"; // size==41 and capacity reuse 47 bytes still allocated.
s.resize(0); // size==0 BUT capacity==47 bytes STILL allocated!!
// swap with scope to force freeing string internals
{
string o;
o.swap(s);
} // size==0 AND capacity==15 (back to smallest footprint possible)
s = "12345"; // size==5 AND capacity==15 (the string is IN the container, no new alloc)
You can treat std::string like any other class. Use new for allocation, and delete once you're done with it.
With C++11, I do not recommend usage of new and delete in most cases. If you need to allocate the string on heap, use std::shared_ptr to wrap it:
std::shared_ptr<std::string> my_string = std::make_shared<std::string>(std::string("My string"));
As soon as all the copies of my_string go out of scope, the associated memory is going to be deleted automatically.