CString Problem
Hello Everybody,
I have a problem regarding CString.
here is the code
struct UserInfo
{
CString cstrUserName;
BOOL blnAccEnabld;
UserInfo *ptrNext;
};
function MyFunction()
{
UserInfo *pUserInfo;
pUserInfo = (UserInfo *)malloc(sizeof(UserInfo));
pUserInfo->cstrUserName = "abc"; // Gives ERROR here
pUserInfo->blnAccEnabld = TRUE; // This works fine
}
Does any body have any idea why such an error???
Thanking You,
Sonali....
Have a Gud Day!!!!!
[579 byte] By [
sss0379] at [2007-11-18 2:14:03]

# 1 Re: CString Problem
Originally posted by sss0379
Hello Everybody,
I have a problem regarding CString.
here is the code
struct UserInfo
{
CString cstrUserName;
BOOL blnAccEnabld;
UserInfo *ptrNext;
};
function MyFunction()
{
UserInfo *pUserInfo;
pUserInfo = (UserInfo *)malloc(sizeof(UserInfo));
pUserInfo->cstrUserName = "abc"; // Gives ERROR here
pUserInfo->blnAccEnabld = TRUE; // This works fine
}
Does any body have any idea why such an error???
Thanking You,
Sonali....
Have a Gud Day!!!!!
I tried your code and i dunnot have any errors.
What errors do u have??
Alin at 2007-11-10 8:56:30 >

# 2 Re: CString Problem
The same code executes properly with me , in release mode tooo..
Whats the problem with you ??
Can you attach the code ??
# 3 Re: CString Problem
This is the problem:
pUserInfo = (UserInfo *)malloc(sizeof(UserInfo));
malloc only allocates memory - it does not construct objects such as CString. Replace it with this:
pUserInfo = new UserInfo;
# 4 Re: CString Problem
Hi...
moodfy the code like this
pUserInfo = new UserInfo; //(UserInfo *)malloc(sizeof(UserInfo));
it should work.
regards,
vikram patwardhan
# 5 Re: CString Problem
Originally posted by 0xC0000005
This is the problem:
pUserInfo = (UserInfo *)malloc(sizeof(UserInfo));
malloc only allocates memory - it does not construct objects such as CString. Replace it with this:
pUserInfo = new UserInfo;
i didn't replace that and it still works ?!
Alin at 2007-11-10 9:00:30 >

# 6 Re: CString Problem
Hi guys,
Thanks a lot for checking. Here is my code.
/* This structure will be useful as a recordset for all getting a list of the Users */
struct UserInformation
{
CString cstrUserName;
BOOL blnUsrCanChangePswd;
UserInformation *Next;
};
/* Function for Getting a list of all Users */
UserRecordset* GetAllUsers()
{
UserInformation *ptrRsUser = NULL;
ptrRsUser = (UserInformation *)malloc(sizeof(UserInformation));
if(ptrRsUser != NULL)
{
ptrRsUser->cstrUserName = "asdf";
ptrRsUser->blnUsrCanChangePswd = FALSE;
ptrRsUser->Next = NULL;
}
}
Its strange if this doesnt give error.
Thanking You,
Sonali....
HAVE A GUD DAY!!!!!
# 7 Re: CString Problem
Hi
Thanks vikram_patwardh, 0xC0000005 it did exactly as u said & it worked.
Thanks,
Sonali....
HAVE A GUD DAY!!!!!
# 8 Re: CString Problem
Originally posted by sss0379
Hi guys,
Thanks a lot for checking. Here is my code.
/* This structure will be useful as a recordset for all getting a list of the Users */
struct UserInformation
{
CString cstrUserName;
BOOL blnUsrCanChangePswd;
UserInformation *Next;
};
/* Function for Getting a list of all Users */
UserRecordset* GetAllUsers()
{
UserInformation *ptrRsUser = NULL;
//ptrRsUser = (UserInformation *)malloc(sizeof(UserInformation));
do as 0xC0000005 suggested!:
ptrRsUser = new UserInformation;
if(ptrRsUser != NULL)
{
ptrRsUser->cstrUserName = "asdf";
ptrRsUser->blnUsrCanChangePswd = FALSE;
ptrRsUser->Next = NULL;
}
}
Its strange if this doesnt give error.
Thanking You,
Sonali....
HAVE A GUD DAY!!!!!
Alin at 2007-11-10 9:03:33 >

# 9 Re: CString Problem
Hi...
i think you are not calling the function
function MyFunction();
thats why you are not getting error :(
regards,
vikram.
Originally posted by myth7676
i didn't replace that and it still works ?!
# 10 Re: CString Problem
Originally posted by myth7676
i didn't replace that and it still works ?! This also may work, but it isn't right:
int main()
{
char *p = "ABCDEF";
p[7] = 'D';
}
What am I trying to say? You were given the correct advice -- get rid of the malloc(), and please replace it with operator new.
Using malloc for such a class invokes undefined behavior, just like the code above that writes beyond the boundaries of an array. It may work, it may crash, you don't know. Right now, your program is ill-formed.
Classes and structures that either have constructors, or whose members contain constructors must be constructed using operator new / new[] if they are created dynamically. The bottom line is never use malloc(), calloc(), or other 'C' allocation functions on classes and structures that contain non-trivial constructors.
Your class has a CString member, and CString has a non-trivial default constructor, therefore your usage of malloc() is illegal and leads to undefined behavior. The malloc() does not call the proper constructors for the class, and your object is not constructed correctly, therefore you are leaving yourself wide open for all kinds of errors. Pretend you've never seen malloc() in your life and the only thing you know of is new / new[] / delete / delete[] :)
Regards,
Paul McKenzie
# 11 Re: CString Problem
Originally posted by vikram_patwardh
Hi...
i think you are not calling the function
function MyFunction();
thats why you are not getting error :(
regards,
vikram.
There is an error, but it may not show itself on your PC because the object is unstable and invokes undefined behavior. It may work, it may crash, there is no telling what may happen since the object was created using malloc() instead of "new".
Regards,
Paul McKenzie
# 12 Re: CString Problem
But CString's = operator is overloeaded operator and handles memory allocation tooo. So there shouldnt be any prblem if malloc is used for object allocation.
On My machine win2k , there is no problem with the code given by sonali , without new operator.
See MFC code.
void CString :: AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
{
AllocBeforeWrite(nSrcLen);
memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(TCHAR));
GetData()->nDataLength = nSrcLen;
m_pchData[nSrcLen] = '\0';
}
const CString& CString :: operator=(LPCTSTR lpsz)
{
ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
AssignCopy(SafeStrlen(lpsz), lpsz);
return *this;
}
#ifdef _UNICODE
const CString& CString :: operator = (LPCSTR lpsz)
{
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
AllocBeforeWrite(nSrcLen);
_mbstowcsz(m_pchData, lpsz, nSrcLen+1);
ReleaseBuffer();
return *this;
}
Here AllocBeforeWrite takes care if CString dont have allocated area to keep the assigned string.
void CString :: AllocBeforeWrite(int nLen)
{
if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
{
Release();
AllocBuffer(nLen);
}
ASSERT(GetData()->nRefs <= 1);
}
void CString :: AllocBuffer(int nLen)
// always allocate one extra character for '\0' termination
// assumes [optimistically] that data length will equal allocation length
{
ASSERT(nLen >= 0);
ASSERT(nLen <= INT_MAX-1); // max size (enough room for 1 extra)
if (nLen == 0)
Init();
else
{
CStringData* pData;
#if !defined(_DEBUG) && !defined(_WIN64)
if (nLen <= 64)
{
pData = (CStringData*)_afxAlloc64.Alloc();
pData->nAllocLength = 64;
}
else if (nLen <= 128)
{
pData = (CStringData*)_afxAlloc128.Alloc();
pData->nAllocLength = 128;
}
else if (nLen <= 256)
{
pData = (CStringData*)_afxAlloc256.Alloc();
pData->nAllocLength = 256;
}
else if (nLen <= 512)
{
pData = (CStringData*)_afxAlloc512.Alloc();
pData->nAllocLength = 512;
}
else
#endif
{
pData = (CStringData*)
new BYTE[sizeof(CStringData) + (nLen+1)*sizeof(TCHAR)];
pData->nAllocLength = nLen;
}
pData->nRefs = 1;
pData->data()[nLen] = '\0';
pData->nDataLength = nLen;
m_pchData = pData->data();
}
}
# 13 Re: CString Problem
Normally when a empty CString Object was created, its StringData structure was forced to point to a fixed memory adress but not NULL.
_AFX_INLINE void CString::Init()
{ m_pchData = afxEmptyString.m_pchData; }
This will esure that all the CString object will work well with all of their functions. If malloc is used to allocate memory for a CString Object, the init() funtion will not be called automatically unless u write codes calling this function.
pUserInfo = (UserInfo *)malloc(sizeof(UserInfo));
pUserInfo ->cstrUserName->Init();
Oh. But Init() is a protected member funtion. :)
So, it cannot pass compiling.
wuyh at 2007-11-10 9:08:40 >

# 14 Re: CString Problem
Originally posted by Krishnaa
But CString's = operator is overloeaded operator and handles memory allocation tooo. So there shouldnt be any prblem if malloc is used for object allocation.You are invoking undefined behavior. Again, you never allocate a structure witn malloc that contains members with non-trivial constructors. How is the constructor for CString ever called if you call malloc? Classes and structures such as the one posted by the OP must be created with operator new, or else the constructors for the objects are not called. That is fundamental ANSI C++ rules. To argue against it is like "spitting in the wind" :)
On My machine win2k , there is no problem with the code given by sonali , without new operator.Again, undefined behavior. I can post code that "works" -- it doesn't mean it's correct. Did you see the tiny example I posted? Is it correct? No. Does it crash? It doesn't on my machine. Does it mean it's right? No. Is it ill-formed? Yes.
Also, why are you looking at the internals of CString? What if it changes in the next version? The bottom line is that there is no need to know what is going on inside of CString or any non-trivial class during construction to see whether malloc is "OK" -- malloc is never OK. Just call "new" and the proper constructor for the object is invoked. This is why a constructor was created -- so that the object can be constructed correctly. If not, why write a constructor?
Regards,
Paul McKenzie
# 15 Re: CString Problem
Originally posted by wuyh
Normally when a empty CString Object was created, its StringData structure was forced to point to a fixed memory adress but not NULL.
_AFX_INLINE void CString::Init()
{ m_pchData = afxEmptyString.m_pchData; }
This will esure that all the CString object will work well with all of their functions. If malloc is used to allocate memory for a CString Object, the init() funtion will not be called automatically unless u write codes calling this function.
pUserInfo = (UserInfo *)malloc(sizeof(UserInfo));
pUserInfo ->cstrUserName->Init();
Oh. But Init() is a protected member funtion. :)
So, it cannot pass compiling. Even if the constructor did nothing, CString is a non-POD (Plain Old Data) type, and non-POD types must have their construcors called for the object to be properly constructed. As I pointed out to Krishnaa, this is fundamental ANSI C++ rules -- it can't be argued to the contrary. What if CString contained members that need to be constructed? The constructor not only calls the constructor for the object, it constructs any other members within the object.
Your example is good, but the reason for why you can't use malloc() shouldn't be based on internal code -- you just can't use malloc on these types. Plain and simple.
Regards,
Paul McKenzie
# 16 Re: CString Problem
Yes Paul , This is a valid answer that Constructors should be called for C++ types...I was confused for a some time even though I was well known to this funda ...it happens with me ..:( :(