|
-
March 2nd, 2012, 07:48 AM
#1
Strange CString behaviour??
Hello,
I have the following code segments:
Code:
CString fooA = TEXT("");
CString fooB = TEXT("");
and then I have a class member/method like this:
Code:
CString* pStr; // this is a pointer to my CString;
void Constructor(CString* str){ // Constructor of my class
this->pStr = str;
}
void doSomething(){ //Member method of my class
*(this->pStr) = TEXT("FOO");
}
When I pass '&fooA' to the constructor of my class and execute 'doSomething' somewhen, the content of 'fooB' changes? How can this be? Every variable in my whole program which has TEXT("") assigned to it changes it's content to "FOO" - did I change TEXT("")'s content??? please help
kind regards,
Michael
Last edited by chaos2oo2; March 2nd, 2012 at 07:52 AM.
-
March 2nd, 2012, 07:58 AM
#2
Re: Strange CString behaviour??
 Originally Posted by chaos2oo2
Hello,
I have the following code segments:
Code:
CString fooA = TEXT("");
CString fooB = TEXT("");
and then I have a class member/method like this:
Code:
CString* pStr; // this is a pointer to my CString;
void Constructor(CString* str){ // Constructor of my class
this->pStr = str;
}
void doSomething(){ //Member method of my class
*(this->pStr) = TEXT("FOO");
}
When I pass '&fooA' to the constructor of my class and execute 'doSomething' somewhen, the content of 'fooB' changes? How can this be?
Instead of bits and pieces of some code, why not post a small, tiny, but complete program that demonstrates this error?
Regards,
Paul McKenzie
-
March 2nd, 2012, 08:06 AM
#3
Re: Strange CString behaviour??
I figured out that this here messed up my programm:
Code:
void CNewDocumentDialog::okClicked()
{
if(m_spsDropDown.GetCurSel() != CB_ERR){
// prepare description for check
CString description;
m_descriptionEdit.GetWindowTextW((LPTSTR)(LPCTSTR)description, m_descriptionEdit.GetWindowTextLengthW() + 1);
description.Trim();
if(description.Compare(TEXT("")) != 0){
CString spsId;
m_spsDropDown.GetLBText(m_spsDropDown.GetCurSel(), spsId);
SPSMap::iterator it_spsMap = this->m_spsMap->find(spsId);
if(it_spsMap == m_spsMap->end()){
C4PEPUtils::DisplayMessage(TEXT("An error occured!"), MB_ICONERROR | MB_OK, this->m_hWnd);
CDialogEx::OnCancel();
return;
}
(*this->m_selIndex) = it_spsMap->second;
(*this->m_description) = description;
CDialogEx::OnOK();
} else C4PEPUtils::DisplayMessage(TEXT("Please enter a description!"), MB_ICONASTERISK | MB_OK, this->m_hWnd);
}else C4PEPUtils::DisplayMessage(TEXT("Please select some SPS!"), MB_ICONASTERISK | MB_OK, this->m_hWnd);
}
and this was the problem:
Code:
CString description; // points internal to TEXT("")
m_descriptionEdit.GetWindowTextW((LPTSTR)(LPCTSTR)description, m_descriptionEdit.GetWindowTextLengthW() + 1); // change content of memory address for TEXT("")
this seems to change the content of TEXT(""). Afterwards it seems to make sense...I took the char array behind description which initially points to TEXT("") and make it's content changeable, so I did change TEXT("").
Last edited by chaos2oo2; March 2nd, 2012 at 08:10 AM.
-
March 2nd, 2012, 08:07 AM
#4
Re: Strange CString behaviour??
Best guess is fooA goes out of scope so you're storing an invalid pointer, but without more code, there's no telling.
-
March 2nd, 2012, 08:12 AM
#5
Re: Strange CString behaviour??
Code:
#include "stdafx.h"
class SomeClass
{
CString *pStr;
public:
SomeClass(CString* str)
{
pStr = str;
}
void doSomething()
{
*pStr = TEXT("FOO");
}
};
int main()
{
CString fooA = TEXT("");
CString fooB = TEXT("");
SomeClass sc(&fooA);
sc.doSomething();
}
The following program shows that only fooA is changed after doSomething is called, just as expected.
So add to the program above the code that duplicates what you're seeing. If you can't, then the bug isn't with CString, it's with the rest of your program.
Regards,
Paul McKenzie
-
March 2nd, 2012, 08:15 AM
#6
Re: Strange CString behaviour??
 Originally Posted by Paul McKenzie
the bug isn't with CString, it's with the rest of your program.
Regards,
Paul McKenzie
That pretty much goes without saying.
-
March 2nd, 2012, 08:16 AM
#7
Re: Strange CString behaviour??
 Originally Posted by Paul McKenzie
Code:
#include "stdafx.h"
class SomeClass
{
CString *pStr;
public:
SomeClass(CString* str)
{
pStr = str;
}
void doSomething()
{
*pStr = TEXT("FOO");
}
};
int main()
{
CString fooA = TEXT("");
CString fooB = TEXT("");
SomeClass sc(&fooA);
sc.doSomething();
}
The following program shows that only fooA is changed after doSomething is called, just as expected.
So add to the program above the code that duplicates what you're seeing. If you can't, then the bug isn't with CString, it's with the rest of your program.
Regards,
Paul McKenzie
Agree...the problem was this:
Code:
CString description; // points internal to TEXT("")
m_descriptionEdit.GetWindowTextW((LPTSTR)(LPCTSTR)description, m_descriptionEdit.GetWindowTextLengthW() + 1); // change content of memory address for TEXT("")
-
March 2nd, 2012, 08:24 AM
#8
Re: Strange CString behaviour??
 Originally Posted by chaos2oo2
I figured out that this here messed up my programm:
So do you think a LPTSTR cast changes a CString into a writeable CString? A CString is not writeable unless you explicitly call the functions to make it writeable.
http://msdn.microsoft.com/en-us/library/awkwbzyc.aspx
See "Modifying CString contents Directly" in the above link.
In general, if a function wants to change the value of a passed-in parameter, unless it is documented that casting will work, it is undefined behaviour to fake out C++ by just casting a const or non-writeable type to a writeable type. Maybe it will work, or maybe it will fail miserably.
Regards,
Paul McKenzie
-
March 2nd, 2012, 08:30 AM
#9
Re: Strange CString behaviour??
 Originally Posted by Paul McKenzie
So do you think a LPTSTR cast changes a CString into a writeable CString? A CString is not writeable unless you explicitly call the functions to make it writeable.
http://msdn.microsoft.com/en-us/library/awkwbzyc.aspx
See "Modifying CString contents Directly" in the above link.
In general, if a function wants to change the value of a passed-in parameter, unless it is documented that casting will work, it is undefined behaviour to fake out C++ by just casting a const or non-writeable type to a writeable type. Maybe it will work, or maybe it will fail miserably.
Regards,
Paul McKenzie
so you don't think this cast above was the source of my problem? Or do you think it was?
-
March 2nd, 2012, 08:37 AM
#10
Re: Strange CString behaviour??
 Originally Posted by chaos2oo2
Agree...the problem was this:
Code:
CString description; // points internal to TEXT("")
m_descriptionEdit.GetWindowTextW((LPTSTR)(LPCTSTR)description, m_descriptionEdit.GetWindowTextLengthW() + 1); // change content of memory address for TEXT("")
So let's see what happens with a simpler program:
Code:
#include "stdafx.h"
class SomeClass
{
CString *pStr;
public:
SomeClass(CString* str)
{
pStr = str;
}
void doSomething()
{
*pStr = TEXT("FOO");
}
};
void SomeWindowsFunc(TCHAR* ptr)
{
ptr[0] = _T('x');
}
int main()
{
CString fooA = TEXT("");
CString fooB = TEXT("");
SomeWindowsFunc((LPTSTR)(LPCTSTR)fooA);
SomeClass sc(&fooA);
sc.doSomething();
}
After the call to SomeWindowsFunc, I've just screwed up the internal reference counting mechanism of CString by circumventing the check to see if the two CStrings fooA and fooB have changed.
The CString class is reference counted. The fooA and fooB are internally pointing to the same memory block since they are initialized to equal values. The CString class makes checks whenever a CString is changed through the public interface of CString to update the reference counts. Since SomeWindowsFunc totally bypasses this, the reference counting scheme is now corrupted.
Regards,
Paul McKenzie
-
March 2nd, 2012, 08:40 AM
#11
Re: Strange CString behaviour??
and after SomeWindowsFunc was called 'fooB'must have been changed too, right?
-
March 2nd, 2012, 08:40 AM
#12
Re: Strange CString behaviour??
 Originally Posted by chaos2oo2
so you don't think this cast above was the source of my problem? Or do you think it was?
Did you read my post carefully? I even showed you the link to how to make CStrings writeable.
You are attempting to make CString writeable by casting. You don't make objects writeable by just casting. See my simple program showing you what happens when you do so.
Regards,
Paul McKenzie
-
March 2nd, 2012, 08:44 AM
#13
Re: Strange CString behaviour??
 Originally Posted by chaos2oo2
and after SomeWindowsFunc was called 'fooB'must have been changed too, right?
Yes. So the issue is again, you can't make things writeable by casting.
I'm trying to get you to understand that the issue is not only with CString, but any C++ type that is either const or not documented to be writeable by just casting.
If a function's parameter is non-const, then casting a const type to non-const as you did will not work, or at the least, is not guaranteed to work. You tried to cast an LPCTSTR into a LPTSTR (const to non-const). What happened? All sorts of funny stuff.
Regards,
Paul McKenzie
-
March 2nd, 2012, 08:45 AM
#14
Re: Strange CString behaviour??
Yes I did, but maybe missed your point of view somehow...maybe my english is not good enough. I know now that I can't just make it writeable by casting my CString.
-
March 2nd, 2012, 08:47 AM
#15
Re: Strange CString behaviour??
GetWindowText takes a CString& as an argument anyway. Why not just pass the CString directly as an argument. All you need is
Code:
CString description; // points internal to TEXT("")
m_descriptionEdit.GetWindowTextW(description);
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|