How to return local array in C++? - c++

char *recvmsg(){
char buffer[1024];
return buffer;
}
int main(){
char *reply = recvmsg();
.....
}
I get a warning:
warning C4172: returning address of local variable or temporary

I would suggest std::vector<char>:
std::vector<char> recvmsg()
{
std::vector<char> buffer(1024);
//..
return buffer;
}
int main()
{
std::vector<char> reply = recvmsg();
}
And then if you ever need char* in your code, then you can use &reply[0] anytime you want. For example,
void f(const char* data, size_t size) {}
f(&reply[0], reply.size());
And you're done. That means, if you're using C API, then you can still use std::vector, as you can pass &reply[0] to the C API (as shown above), and reply to C++ API.
The bottomline is : avoid using new as much as possible. If you use new, then you've to manage it yourself, and you've to delete when you don't need it.

You need to dynamically allocate your char array:
char *recvmsg(){
char* buffer = new char[1024];
return buffer;
}
for C++ and
char *recvmsg(){
char* buffer = malloc(1024);
return buffer;
}
for C.
What happens is, without dynamic allocation, your variable will reside on the function's stack and will therefore be destroyed on exit. That's why you get the warning. Allocating it on the heap prevents this, but you will have to be careful and free the memory once done with it via delete[].

The warning message is correct. You're returning the address of a local array which disappears after the function returns.
You can do this using dynamic memory allocation:
char *recvmsg(){
char *buffer = (char*)malloc(1024);
return buffer;
}
The catch is that you need to make sure you free() the pointer later on to avoid a memory leak.
Alternatively, you can pass the buffer into the function.
void recvmsg(char *buffer,int buffer_size){
// write to buffer
}
void main(){
char buffer[1024];
recvmsg(buffer,1024);
}
This avoids the need for a memory allocation. This is actually the preferred way to do it.

The problem is that buffer lives on the stack and goes out of scope the moment you exit recvmsg.
You could allocate buffer on the heap:
char *recvmsg(){
char *buffer = malloc(1024);
return buffer;
}
Note that now the caller is responsibe for disposing of the allocated memory:
void main(){
char *reply = recvmsg();
free(reply);
}

You have a few options...The way you're doing it now is going to cause undefined behavior as the array will go out of scope once hte function returns. So one option is to dynamically allocate the memory..
char * recmsg()
{
char * array = new char[128];
return array;
}
Just remember to clean it up with delete this way (or free if you used malloc). Second, you could use a parameter...
void recmsg(char * message, int size)
{
if (message == 0)
message = new char[size];
}
Again, the same thing goes for clean up here as with the previous. Also note the check for 0 to make sure you don't call new on a pointer that's been allocated already.
Last, you could use a vector..
std::vector<char> recmsg()
{
std::vector<char> temp;
//do stuff with vector here
return temp;
}

char *recvmsg(){
char *buffer = new char;
cout<<"\nENTER NAME : ";
cin>> buffer;
return buffer;
}
int main(){
char *reply = recvmsg();
cout<<reply;
}

Just to complete the picture:
It is not necessary, to allocate memory with malloc. You can also create the buffer on the stack, but you must create it on a stack frame that lives as long as the consumer of the buffer lives. That was the error of the OP -- when the callee was finished, the buffer was deleted and the caller got a invalid pointer.
So what you can do is this:
void recvmsg(char *buffer, size_t size) {
... do what you want ...
}
void main(void) {
char buffer[1024];
recvmsg(buffer, sizeof(buffer));
}

You could dynamically create the buffer, but then the caller needs to know to free it.
I think it's better to pass in a buffer (assuming recvmsg also fills it)
void recvmsg(char *buffer, size_t size){
}
void main(){
char buffer[1024];
recvmsg(buffer, sizeof(buffer));
}
Even if the caller decides dynamic is better, they will know that they need to free it, and the specific way to do that (free(), delete, delete[], or perhaps something special from a custom allocator)

The problem is that you are returning a pointer to a buffer allocated on the stack. Once the function returns, that buffer is no longer valid.

You are allocating the array on the stack inside of your recvmsg function. Returning a pointer to that memory will at some point lead to undefined behavior if it is dereferenced as the memory will be cleaned up when the function exits.
If you want to return a pointer to memory you will need to allocate it dynamically using malloc.

when you are returning the buffer then as it acting as a pointer to the first location of the array so it will return its address.And the place where you are calling the function there you can make a character pointer which will store this returned address value .After which you can move your pointer and can access all the elements of your array.

how about passing by ref
char buf[1024];
PutStuffInBuff(&buf);

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.

copy char* to another char** using dynamic allocation

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.

returning a char* array as string -> memory leak?

std::string Client::listenForMessage()
{
// ... receiving message size ...
char* message = new char[messageSize];
message[messageSize] = '\0';
// ...
... recv(connectedSocket, message, messageSize, 0);
// ...
return message;
}
Actually everything seems to work fine, but I'm not sure.
Do I have to delete/free my message variable before I return it? Or does the conversion to string handle that for me?
It's a leak.
Do I have to delete/free my message variable before I return it?
Yes.
Or does the conversion to string handle that for me?
No, std::string doesn't take ownership of pointers passed to its constructor. (There's no way for it to know whether it was new'd or not.)
There is very rarely need to manage your own dynamic arrays. The Object Oriented way to manage an array is using the std::vector class. It does all the creating/deleting for you.
So I would use a std::vector like this:
std::string Client::listenForMessage()
{
// ... receiving message size ...
// create a vector to manage the message array
std::vector<char> message(messageSize);
// ...
// use data() and size() methods
... recv(connectedSocket, message.data(), message.size(), 0);
// ...
// construct the returned string from the vector data
// The vector cleans itself up automatically
return {message.begin(), message.end()};
}
It may cause memory leak, or it may crash when you write out-of-range.
message[messageSize] = '\0'; is illegal out-of-range access, so remove it or change to
if (messageSize > 0) message[messageSize - 1] = '\0';
or something that you want and valid.
Then, to avoid memory leak, delete the string before returning, or the pointer to allocated memory will be lost.
std::string ret = message;
delete[] message;
return ret;
Passing data read from recv() in this way without checking is not a good idea because it might not be a null-terminated string.

Accessing array elements from char*

I'm new to c++ and am still struggling with the whole pointer thing.
Let's say I have a function that returns a char* pointing to the start of an array of characters / a string.
char* read() {
char data[] = "this for example";
return *data;
}
then later I want to access this data, but I don't think I can do something like this:
char* data = read();
if(data[3] == 's')
return true;
what is the right way to use the data returned by read() in this example?
In this case it is better to use standard class std::string
std::string read()
{
char data[] = "this for example";
return data;
}
//...
std::string data = read();
if( data[3] == s )
return true;
As for your code snippet then if to rewrite it without errors it would have undefined behaviour because you return a pointer to a local array that will be destroyed after exiting the function.
In your read() function, return *data; returns a char not a char*. Also stack memory is not supposed to be accessed after your function returns. Make it static. It should be:
char* read()
{
static char data[] = "this for example";
return data;
}
You can't return pointer to an automatic variable. It invokes undefined behavior. Allocate data dynamically.
char *data = new char[20];
Do not forget to delete the allocated memory when you are done by using
delete[] data;
Better to use std::vector or std::string instead.

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;