When do I need to deallocate memory? - c++

I am using this code inside a class to make a webbrowser control visit a website:
void myClass::visitWeb(const char *url)
{
WCHAR buffer[MAX_LEN];
ZeroMemory(buffer, sizeof(buffer));
MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, url, strlen(url), buffer, sizeof(buffer)-1);
VARIANT vURL;
vURL.vt = VT_BSTR;
vURL.bstrVal = SysAllocString(buffer);
// webbrowser navigate code...
VariantClear(&vURL);
}
I call visitWeb from another void function that gets called on the handlemessage() for the app.
Do I need to do some memory deallocation here?, I see vURL is being deallocated by VariantClear but should I deallocate memory for buffer?
I've been told that in another bool I have in the same app I shouldn't deallocate anything because everything clear out when the bool return true/false, but what happens on this void?

I think you have some fundamental problems with your understanding of memory management. In this case, no, you don't need to explicitly free any memory. You didn't ever call new, so you don't need to call delete. buffer exists only on the stack, and will vanish when this method returns.

If I might, I'd suggest doing this a bit differently -- I'd start by creating a small class:
class bstr {
VARIANT content;
public:
bstr(char const *url) {
WCHAR buffer[MAX_LEN] = {0};
MultiByteToWideChar(CP_ACP,
MB_ERR_INVALID_CHARS,
url,
strlen(url),
buffer,
sizeof(buffer)/sizeof(buffer[0])-1);
content.V_T = VT_BSTR;
content.bstrVal = SysAllocString(buffer);
}
operator VARIANT const &() { return content; }
~bstr() { VariantClear(&content); }
};
Then your code would change to something like:
void myClass::visitWeb(const char *url) {
your_control.Navigate(bstr(url));
}
and all the allocation and freeing gets handled automatically from there.
Even if you don't do use a class like this, note the change to the call to MultiByteToWideChar. The last parameter is supposed to be the number of WCHAR elements in the buffer, not the number of chars. As it is, you've set up a buffer overrun...

I don't see any news, so I wouldn't expect any deletes.
I guess I'd look at the description of SysAllocString() to see if it allocates any memory that you need to get rid of yourself.

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.

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.

Free allocated pointer passed to a function?

When shall I free my unsigned char* if I need to pass the unsigned char* into a function?
Example
void myFunction(unsigned char *request){
// do I need to use free(request); here?
}
int main (){
// main code
unsigned char *request = NULL;
// read from buffer and reallocate memory (using realloc & memcpy)
myFunction(request); // I do not want to read or use "request" after this function call.
free(request); // is this ok? Or should this be inside myFunction also?
return 0;
}
Use free() on something as soon as you're done using it. So for instance, you probably wouldn't do it inside myFunction() because you're probably still going to be interested in the value pointed at by request when you exit that function back to main.
Usually you have to free it where you have allocated it, and don't need more it.
In This case you can do it in both places, but also, after freed set it to NULL, and next time when you'll try to free it, check for null
also you mai implement something like:
void FreeAndNull(void *request){
if request <> NULL then
{ free(request); request = NULL; }
}
You don't have to do this - but a good practice is to free things at the same level as you allocated them. E.g. don't allocate something in a function and free it after it is returned. Because then the lifecycle of the memory is not clear to you months later when you look at the code again.
So it is much better to:
request = malloc();
doStuff( request );
free( request );
than the pattern you have. C++ helps you with this pattern by creating constructors and destructors. That is a constructor may actually allocate memory and essentially return it to you in the form of an object, but the compiler will automatically call the destructor for you freeing the memory.
So you can achieve something like the pattern you want with a much safer and more maintainable pattern if you wrap that request buffer in a class:
Request::Request() { mRequest = malloc(); }
Request::~Request() { if ( mRequest ) free( mRequest ); mRequest = NULL; }
...
{
Request request;
myFunction( request );
}
With this pattern you memory is cleaned up automatically. Safer and more maintainable.

Copy and Store LPTSTR in class causes crash

I am attempting to copy a LPTSTR and store that string as a member variable in an object. But my attempts to copy the LPTSTR seem to fail and when I go to access/print the value of the copied LPTSTR I get a program crash.
Is it possible to copy a LPTSTR and store it in my class below or is it better to just use a TCHAR*?
class Checkbox
{
private:
LPTSTR text;
HWND hwnd;
public:
Checkbox(HWND nHwnd, LPTSTR nText)
{
lstrcpy(checkText, text);
}
void print()
{
// Causes a crash
MessageBox(hwnd, text, text, MB_OK);
}
};
LPTSTR is just a pointer. So, you need to take care to allocate memory before using it. So is the case with TCHAR*. Alternatively you could use wstring, if you have to worry about unicode strings.
You copy to an uninitialized pointer, which will overwrite some random area in memory. You need to allocate memory for the pointer first, and also remember to free the memory when you don't need it anymore.
Like the other answers have said, you need to allocate memory to "LPTSTR text" before you can use it.
Get the length of the string (strlen should do) you want to copy and then allocate the memory like this:
text = TCHAR[length];
You can declare a deconstructor for your class to delete the allocated memory when the program ends or the program leaves the scope of the class instance.
~CheckBox()
{
if (text)
delete[] text;
}
You should also create another constructor with no parameters that sets text to NULL;

How to return local array in 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);