copy char* to another char** using dynamic allocation - c++

I am still new in this topic but can someone explain me how can I copy one char* to another char** as parameter without getting memory leaks?
void Hardware::copyString(char** dest, const char* source)
{
size_t length = strlen(source);
auto string = new char[length+1];
strncpy(string, source, length);
string[length] = '\0';
*dest = string;
//need to be freed
free(string); //if i free here the data would getting lost
}
and a ctor:
Hardware::Hardware(const char* name, int cost)
{
copyString(&name_, name);
cost_ = cost;
}
main.cpp
Hardware hard("CPU", 250)
Where should I free this without getting memory leaks and have the right output?

Regardless of the issues in your implementation, the simple answer to your question would be to free it at the destructor.
If you don't want to expose the name_ variable, you can free it inside the destructor of the Hardware class.
Hardware::~Hardware()
{
delete[] name_;
}
If you free is inside the function itself, you're deleting the heap allocation, even though you're passing different variables, because they're pointing to the same memory location.
But, as others suggested, the best way to work with strings is to use std::string.

Related

using "new" and "delete" inside class function

I want to be sure that using new and delete to free heap memory is done as needed.
Following function returns a char *. Inside each function I use new for the returned value, and I delete afterwards.
Is it the right way to free heap memory for function return?
const char *myIOT2::_devName()
{
char *ret = new char[MaxTopicLength2];
if (strcmp(addGroupTopic, "") != 0)
{
snprintf(ret, MaxTopicLength2, "%s/%s/%s", prefixTopic, addGroupTopic, deviceTopic);
}
else
{
snprintf(ret, MaxTopicLength2, "%s/%s", prefixTopic, deviceTopic);
}
return ret;
}
const char *myIOT2::_availName()
{
char *ret = new char[MaxTopicLength2];
const char *DEV = _devName();
snprintf(ret, MaxTopicLength2, "%s/Avail", DEV);
delete DEV;
return ret;
}
To point out: the fact the I DEV: const char *DEV = _devName(); in order to use it as a parameter in snprintf(ret, MaxTopicLength2, "%s/Avail", DEV); just to be able to delete it later as delete DEV; - is this correct?
At least as I see things, you really only have two sane choices here. One is for the caller to handle all the memory management. The other is for the callee to handle all the memory management.
But what you're doing right now (callee handles allocation, caller handles de-allocation) is a path to madness and memory leaks.
If the caller is going to manage the memory, this all becomes fairly simple:
const char *myIOT2::_devName(char *ret, size_t maxlen)
{
if (strcmp(addGroupTopic, "") != 0)
{
snprintf(ret, maxlen, "%s/%s/%s", prefixTopic, addGroupTopic, deviceTopic);
}
else
{
snprintf(ret, maxlen, "%s/%s", prefixTopic, deviceTopic);
}
return ret;
}
If the callee is going to handle all the memory management, you'd normally use std::string. Since you're on an Arduino, however, std::string isn't available, and you need to use their own String class instead. Either way, you simply allocate a String object and put your contents into it. It takes care of the actual memory allocation to hold the contents, and will free its contents when the String object is destroyed.
Given the small amount of memory normally available on an Arduino, having the caller allocate the memory is usually going to work out better. But (especially if this is something that doesn't happen very often, so you won't run into heap fragmentation problems) allocating space on the heap can work reasonably well also.
But I'll repeat: trying to mix memory management so the callee allocates and the caller deletes...is the stuff of nightmares. When you read about C++ circa 1993, and hear about lots of problems with memory leaks...this is exactly the sort of thing that led to them.
ret allocated memory:
const char *myIOT2::_devName()
{
char *ret = new char[MaxTopicLength2];
return ret;
}
And below, you'll see that by deleting DEV, you will free the memory, because it's actually ret. But this time, you should remove ret2 somewhere else since it's the return value and there's no way to delete it inside that scope:
const char *myIOT2::_availName()
{
char *ret2 = new char[MaxTopicLength2];
const char *DEV = _devName();
delete[] DEV;
return ret2;
}
Also, note the following:
char* str = new char [30]; // Give str a memory address.
// delete [] str; // Remove the first comment marking in this line to correct.
str = new char [60]; /* Give str another memory address with
the first one gone forever.*/
delete [] str; // This deletes the 60 bytes, not just the first 30.

How do I save a string Variable of a Class on the heap using new

I have a problem,
I have to write a paper about Dynamic Memory Management in C++, however I never learned C++.
For my example code I want to show, why you need to use a Deconstructor if you allocate memory using new in your Class. But I can't get my code to work.
How do I write my Constructor, so that the string name gets allocated with the new operator?
Code i already have:
class Studi
{
private:
unsigned int matNr;
char* name;
public:
Studi(const string& k_name, unsigned int k_matNr)
{
name = new char[k_name.length()];
strcpy(name, k_name);
matNr = k_matNr;
}
};
thanks for any help :)
You have to allocate one more byte for the terminating null-character.
You can use c_str() to obtain C-style string from std::string.
Studi(const string& k_name, unsigned int k_matNr)
{
name = new char[k_name.length() + 1];
strcpy(name, k_name.c_str());
matNr = k_matNr;
}
Also don't forget to follow The Rule of Three to avoid memory management troubles when the object is copied.

How to efficiently move underlying data from std::string to a variable of another type?

EDIT: Sorry everyone, I don't think this toy example really reflected my problem. What I should have asked is if there is a way to release a std::string object's buffer. There is not, and that makes sense. Thanks!
Suppose I have the following (broken) code:
void get_some_data(MyCustomContainer& val)
{
std::string mystr = some_function();
val.m_data = &mystr[0];
}
This won't work, because the memory pointed by mystr is freed at the end of get_some_data, and the memory referenced by val.m_data will be invalid.
How can I tell a std::string "Don't free your memory buffer at your destructor!" ? I don't want to copy the data. The MyCustomerContainer object will handle the memory free-ing at its destructor.
You cannot do this without breaking the rules. The std::string class is not allowed to release its ownership explicitly. In fact, a std::string might not even have any memory allocated due to SBO optimization:
std::string str1 = "not allocating";
std::string str2 = "allocating on the heap, the string is too large";
This behavior is completely platform- and implementation-dependent. If a string doesn't allocate its buffer on the heap, the data is placed on the stack, which doesn't need de-allocation.
{
std::string str1 = "not allocating";
} // no buffer freed
So even if there were a way to tell the string not to de-allocate its buffer, there is no way to tell if the buffer is managed on the heap or not.
Even if there were a way to tell if the string uses the stack, you'd have to allocate a buffer in place as a class member and copy its content.
The idea of transferring a string's data and stealing its ownership over that string's memory resource is fundamentally broken as you can't get away without copying, simply because there might be no ownership to steal.
What I recommend is for you to copy the string content in all cases if you don't want to change how MyCustomContainer works:
void get_some_data(MyCustomContainer& val)
{
std::string mystr = some_function();
val.m_data = new char[mystr.size()];
std::memcpy(val.m_data, mystr.data(), mystr.size());
}
In contrast, if you allow MyCustomContainer to store a std::string, you could actually get away without copying when a buffer is allocated by moving the string:
void get_some_data(MyCustomContainer& val)
{
// let m_data be a std::string
val.m_data = some_function();
// The above is equivalent to this:
// std::string mystr = some_function();
// val.m_data = std::move(mystr);
}
Moving a string will invoke move assignation. With move assignation, the string implementation will transfer the ownership of the mystr's buffer into m_data. This will prevent any additional allocation.
If mystr didn't allocate, then the move assignment will simply copy the data (so no allocation there, either).
The right way to fix this problem is:
class MyCustomContainer {
public:
std::string m_data;
};
void get_some_data(MyCustomContainer& val) {
val.m_data = some_function();
}
The get_some_data could even be made into a member function, which would make the usage even easier at the callsite, and perhaps allow m_data to be private instead of exposed.
If .m_data is an std::string you can take advantage of std::string's move-assignment operator:
val.m_data = std::move(mystr);
If m_data is not an std::string you are pretty much out of luck, the internal buffer is inaccessible (as it should be).
No, you cannot. std containers will only give up their managed memory (and then only sometimes) to std containers of the same type.
For string this would be impossible regardless, as most implementations do a short string optimization and store short strings internally.
You could throw the std string into a global buffer somewhere and reap it at cleanup, but that gets insanely complex.
If you want you can use this code that causes Undefined Behavior, so it should not be used, but if you are working on some toy project of your own that will be quickly abandoned you can see if it works for you.
// REQUIRES: str is long enough so that it is using heap,
// std::string implementation does not use CoW implementation...
// ...
char* steal_memory(string&& str){
alignas(string) char buff[sizeof(string)];
char* stolen_memory = const_cast<char*>(str.data());
new(buff) string(move(str));
return stolen_memory;
}
If you want to handle short string you should add malloc and copy from buffer for that case.
Main idea here is to use placement new that takes the ownership from our input string, and not calling the destructor on string in buff. No destructor means no calls to free, so we can steal memory from the string.
Unfortunately const_cast is UB in this case so like I said you should never use this code in serious code.
You can do mystr static
void get_some_data(MyCustomContainer& val)
{
static std::string mystr;
mystr = some_function();
val.m_data = &mystr[0];
}
but, in this way, you have only one mystr for all get_some_data() calls; so
get_some_data(mcc1);
get_some_data(mcc2);
// now both `mcc1.m_data` and `mcc2.m_data` point to the same value,
// obtained from the second `some_function()` call
If you can compile-time enumerate the calls to get_some_data(), you can differentiate your mystr using a template index
template <std::size_t>
void get_some_data(MyCustomContainer& val)
{
static std::string mystr;
mystr = some_function();
val.m_data = &mystr[0];
}
get_some_data<0U>(mcc1);
get_some_data<1U>(mcc2);
// now `mcc1.m_data` and `mcc2.m_data` point to different values

Exception Error in Destructor

I know this is very basic but somehow working on different technologies I have mashed up my C++ concepts
I have created a simple program but it is giving exception when the destructor is called.
Below is the code:
#include "stdafx.h"
#include<iostream>
using namespace std;
class Employee
{
public:
Employee(char *name){
cout<<"Employee::ctor\n";
myName_p = new char(sizeof(strlen(name)));
myName_p = name;
}
void disp(){cout<<myName_p;}
~Employee()
{
cout<<"Employee:dtor\n\n";
delete myName_p;
}
private:
char *myName_p;
};
int main()
{
Employee emp("check");
emp.disp();
return(0);
}
Requesting all to clear this basic concept. As per my understanding we can't use delete[] because we are not using new[] in this case. Though I have tried using delete[] , but still it was giving error
You REALLY should use std::string here.
It is so much easier, especially for a beginner. The list of errors is:
you are calculating the wrong size of the name, it should be strlen(name)+1, not using sizeof anything.
You also should use new char[strlen(name)+1].
You are copying the data from the string supplied as the argument to the constructor, use strcpy rather than name_p = name - the latter leaks the memory you just allocated, and then you have a pointer to a const char * which you should not delete.
If you fix the allocation so that it is correct, you should then use delete [] name_p;.
However, it you instead use std::string, all of the above problems go away completely, you can just do:
Employee(char *name) name_p(name) { ... }
and get rid of all the problematic new, delete and copying. Of course, name_p is probably no longer a suitable name for the variable, but you get the idea.
Change
myName_p = new char(sizeof(strlen(name)));
myName_p = name;
to
myName_p = strdup(name);
and #include <cstring>. This creates new space and copies the parameter string. In this way, you'll have to call free instead of delete in your destructor.
Otherwise, after the second assignment, you have assigned the string literal "check" to myName_p, and the newly created space is discarded. Then your destructor tries to delete "check" rather than the allocated space, which results in crash.
Also, it is better practice to use std::string rather than old char* strings:
class Employee
{
public:
Employee(char *name): myName_p(name) {
cout<<"Employee::ctor\n";
}
void disp(){ cout << myName_p; }
private:
std::string myName_p;
};
The string class will manage memory for you.

Destructor on const char *

In my program, i have line like this:
const char * str = getStr();
Do i need to call destructor on str [] at the end of function to prevent memory leaks?
Question does not contain enough information to tell, it depends what getStr() does. For example:
const char *getStr() {
return "boo";
}
then you must not call delete.
const char *getStr() {
return new char;
}
then you should call delete str; to avoid a memory leak (and must not call delete[]).
const char *getStr() {
return new char[10];
}
then you should call delete[] str; to avoid a memory leak (and must not call delete).
const char *getStr() {
return 0;
}
then it doesn't matter what you do, calling any kind of delete on str has no effect.
Ownership of resources, and how to release any resources owned, are part of the interface to a function, and should be documented at the same time as you document what the return value actually is.
It all depends on what getStr() does. It may even be that you have to call free on the pointer if getStr() created it with malloc. It may be that getStr() is returning a pointer to a static area (not very thread safe, but it happens) or any number of other things.
Part of the contract and documentation for getStr() should be who owns the pointer it returns.
Here are some examples of possible getStr() functions...
In this case getStr() owns the pointer and you don't have to do anything to free it. OTOH, what's being pointed at may change the next time you call getStr() so you should probably make your own copy if you need to keep it around for any length of time:
const char *getStr()
{
static char buf[30] = "Silly counter";
buf[0] = buf[0] + 1;
return buf;
}
In this case, you will eventually need to call free on the pointer returned:
const char *getStr()
{
return strdup("Silly string");
}
In this case, you will need to call plain old delete on the pointer returned:
const char *getStr()
{
return new char;
}
In this case, you will need to call delete [] on the pointer returned:
const char *getStr()
{
return new char[50];
}
There are many other possibilities. As I stated previously, part of the contract for a function (which should appear in its documentation) is who owns the pointer returned and how that data pointed to must be disposed of if doing so is the caller's responsibility.
It depends on how getStr() has been designed. It could return a pointer to a string that is still owned by someone else (and in this case the answer is no) or it may return a pointer to and the caller becomes the owner (and in this case the answer is yes).
You should check the documentation of getStr to know.
If the ownership of the returned area is of the caller then probably in C++ returning an std::string would have been a much better idea.
It's a good idea to do so if it's going out of scope. I'd recommend also setting the pointer to null to ensure it isn't dangling:
delete[] str;
str = null;