I hope the title was good enough to help explain what I am having problems with. I think once I solve this problem my project will be pretty much finished. Just a note, both projects are compiled under Unicode.
I am working with a CLI/C++ DLL that takes in a LPCTSTR and returns a const char*. If I store the value of the return in a const char* in my project while stepping through I can see the value its returning is what I expect to be returned.
Now if I do the following:
LPCTSTR strValue = L"test";
const char* Return = MethodCall(strValue);
LPCTSTR Final = CString(Return);
Return will equal "Xmkk=Asmks" (which is what it should). This method encrypts a string. The problem is when I do CString, Final will equal "ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ㹙癞鞮᠀諸²⤐²". How do I turn the onst char* into a LPCTSTR without changing its data"
Thank you.
After CString(Return) is destructed (this happens "right on next line after its construction") "Final" pointer is pointing to dealocated chunk of memory (which was internal CString(Return) buffer). At this point contents of memory to which it points is undefined and dereferencing it is undefined behaviour.
To use pointer to internal buffer safelly you should ensure that CString which owns buffer is alive as long as pointer is.
LPCTSTR strValue = L"test";
const char* Return = MethodCall(strValue);
LPCTSTR PointerToBuffer= 0;
{
CString ReturnStringObj(Return);
PointerToBuffer = ReturnStringObj;
// Can safelly use your pointer here
}
// Here ReturnStringObj is killed and pointer dereferencing is invalid here
As vnm mentions, you're creating a temporary CString object by calling its constructor in line 3, and then that object gets immediately destroyed. This deallocates the chunk of memory it was using for your buffer, meaning that any attempts to access the data stored in that memory would be undefined behavior. That's why your string looks garbled: it's already been deleted.
If you're new to C++, you need to make sure that you understand object lifetimes. That would make writing this code significantly simpler.
The solution is to ensure that your CString object does not get destroyed until you're finished with it. If you only need the object to exist within your function, you can leave it as a temporary object created inside of that function. If you need it to exist outside of that function, you'll need to create it at a higher level or save a pointer to it.
Note that CString objects are implicitly convertible to a LPCTSTR.
So assuming that you only need the CString object to stay alive within the scope of your function, you could write the following code:
{
// Declare a string literal
LPCTSTR strValue = L"test";
// Encrypt the string
const char* strReturn = MethodCall(strValue);
// Create a CString object representing the encrypted string
CStringA myString(strReturn);
// Do something with myString, like display it in a message box
// (Remember that it's an ANSI (non-Unicode) string!)
// ...
MessageBoxA(NULL, myString, NULL, MB_OK);
// ...
// myString (your CString object) gets destroyed here
}
What you can do is create a new CStringA object and cast this to const char* for Final. Then Final will remain valid as long as the CStringA is defined.
I'd recommend against using a CString (or CStringW) for storage that you will need to access using const char*.
Related
Please bear with me, i have been a c++ programmer for a little while.
I need to know if i am doing this wrong. It works, but i suspect it causes a memory leak. I have this function:
_bstr_t WCH2BSTR(wchar_t* st)
{
BSTR stres = SysAllocString(st);
return (_bstr_t)stres;
}
Let's say i were to use the result like this:
wcout << WCH2BSTR(wCharArr) << " done." << endl;
Will this cause a memory leak, or will the BSTR be deleted by a "garbage collector" like in Java?
If it is a memory leak, how can i prevent it without losing the ability to do it as a one-liner? Sometimes the results of WCH2BSTR are stored in a BSTR variable and disposed of properly, but i would like to use the same function for concatenating wchar_t to BSTR's as well in a one-liner fashion.
Thanks.
You have a memory leak. But it's subtle:
This line:
BSTR stres = SysAllocString(st);
Allocates a BSTR as you expect.
However, the return statement:
return (_bstr_t)stres;
Triggers a call to the _bstr_t(const wchar_t*) constructor, not the which in turn will allocate another BSTR via SysAllocString. So you've leaked a string from the initial call.
This is likely closer to what you want:
_bstr_t WCH2BSTR(const wchar_t* st)
{
return _bstr_t(str);
}
The constructor of _bstr_t will do the SysAllocString thing for you. The destructor of _bstr_t will do the SysFreeString thing for you.
But...
Be careful of saying this:
BSTR bstr = WCH2BSTR(L"Foo");
Because that will compile! But after the assignment to a raw BSTR, the destructor of the _bstr_t returned by the helper function will get invoked and free the already returned pointer.
What you really want to do is to just avoid the helper function altogether and say this explicitly in your code:
_bstr_t bstr = L"Foo";
When the _bstr_t goes out of scope, so does the underlying BSTR that it holds.
I am trying to program a qt widget application which deals with linked list of nodes, the node contains 3 char* data member and 2 int members and a "next" pointer of "node" type,
my issue is the char* members in nodes of the linked list are getting saved same as the third char* member, I tried using debugger and found out that
the length of all the 3 ints i.e. lentitl,lenpub,lenpub are initialized to same value, and all the 3 char* members are getting same value,
the node constructor is as follows
node::node(char* titl,char* auth,char* pub,int pri,int stockp)
{
int lentitl,lenauth,lenpub;
lenpub=strlen(pub);
lentitl=strlen(titl);
lenauth=strlen(auth);
title=new char[lentitl+1];
author=new char[lenauth+1];
publisher=new char[lenpub+1];
strcpy(title,titl);
strcpy(author,auth);
strcpy(publisher,pub);
price=pri;
stockposition=stockp;
next=NULL;
}
the node functions if called from another class function named "addbook",and addbook is called from mainwindow.cpp, the functions calls for addbook is as follows
void MainWindow::on_addbook_clicked()
{
char *titl,*auth,*pub;
int pri,stockp;
titl=ui->title->toPlainText().toLatin1().data();
auth=ui->author->toPlainText().toLatin1().data();
pub=ui->publisher->toPlainText().toLatin1().data();
pri=ui->price->toPlainText().toInt();
stockp=ui->stockposition->toPlainText().toInt();
p.addbook(titl,auth,pub,pri,stockp);
}
and the function call for node is as follows
void shop::addbook( char *titl, char *auth, char *pub, int pri, int stockp)
{
node *p=new node(titl,auth,pub,pri,stockp);
if(start==NULL)
{
start=p;
end=p;
}
else
{
p->next=start;
start=p;
}
}
the zip of whole project is here
and here is the link to the ouput
the screen shot of the output is
as you can see in the image,string entered at "publisher" textedit is getting set to all 3 char* of the node,
can anyone explain me why is this happening?
titl=ui->title->toPlainText().toLatin1().data();
This is probably the issue: toLatin1() returns a new QByteArray which owns its data. You assign the internal data pointer of that QByteArray to titl. However, the QByteArray is only a temporary variable and will get destroyed in the next line of code. When the QByteArray gets destroyed, it will free its data, which means your titl is now pointing to memory that was already freed - i.e. titl points to an invalid memory location.
Suggested solution alternatives:
Use QString instead of char* in your node class, much easier to deal with memory management issues that way
Make sure your QByteArray temporary lives as long as you need the data (until you strcpy the data):
QByteArray titl = ui->title->toPlainText().toLatin1();
QByteArray auth = ui->author->toPlainText().toLatin1();
QByteArray pub = ui->publisher->toPlainText().toLatin1();
pri=ui->price->toPlainText().toInt();
stockp=ui->stockposition->toPlainText().toInt();
p.addbook(titl.data(),auth.data(),pub.data(),pri,stockp);
I'm not expert of Qt but there is something that doesn't sound good to me in terms of C++. Mainly a function in your code is returning a "char * " pointer instead of a "const char*", I'm talking about these lines:
char *titl,*auth,*pub;
int pri,stockp;
titl=ui->title->toPlainText().toLatin1().data();
If the data was directly provided by the title class I expect to obtain a const char* pointer in order to do not be allowed to modify it. The only reason you can handle a char* ( or in other words a well known library is designed to return a non const pointer) is that there is a temporary object or a static buffer in the middle of the calls: toLatin1 or data.
Reading the docs of Qt: toLatin1 is returning a temporary object, a QByteArray.
QByteArray toLatin1 () const
for more information: http://qt-project.org/doc/qt-4.8/qstring.html
So simply modify each string request like:
QByteArray titlArray = ui->title->toPlainText().toLatin1();
titl=titlArray.data();
in that way each string will point to a still existing buffer when you are calling
p.addbook(titl,auth,pub,pri,stockp);
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
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;
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.