PDA

View Full Version : char* to QString. Segfault after delete []



TheRonin
16th June 2008, 18:30
Hello,

In the application I'm working on, i've got a class CfgMgr with a method: getValue() that's supposed to return a QString:


QString CfgMgr::getValue()
{
QString qstrValue;
char* cstr = 0; // null pointer
if (Get_Value(&cstr)){ // external call that allocates memory using 'new'
qstrValue = cstr; // copies the data?
delete [] cstr;
}
return qstrValue;
}

QString myValue = CfgMgr::getValue();


This works fine most of the time, but sometimes the application segfaults at qatomic_i386.h:80 after coming from QString::operator=(..)

I suspect that the problem is one of dangling pointers. I tried doing the following since QByteArray supposedly performs a deep copy:



QString CfgMgr::getValue()
{
QString qstrValue;
char* cstr = 0; // null pointer
if (Get_Value(&cstr)){ // external call that allocates memory using 'new'
QByteArray ba(cstr); // deep copy
delete [] cstr;
qstrValue = ba;
}
return qstrValue;
}
QString myValue = CfgMgr::getValue();


Unfortunately, this does not seem to work either. This might just be the symptom of a problem created elsewhere but it's not unlikely that i've made a mistake here either.

Does anyone see any obvious errors ?

Any help would be greatly appreciated.

marcel
16th June 2008, 18:35
The first version is correct. Can you post the GetValue function?

TheRonin
17th June 2008, 08:47
Unfortunately i can't since the Get_Value function is part of an external library (of which i don't have the source) that performs reading and writing of configuration data to file. All i've got to go on is that the documentation says it does 'new' on the char* buffer i provide and copies the config data into it.

I feel pretty comfortable assuming the Get_Value function does what it says it does and that the problem lies in my code somewhere. But if it's not with my use of QString and char* then i'm at a total loss.

marcel
17th June 2008, 09:10
What does Get_Value returns? Is it a bool or the length of the string? Check if the allocated char* is null terminated after Get_Value returns...

TheRonin
17th June 2008, 10:33
Get_Value returns a bool signifying if the operation succeeded or not.

I'm a bit uncertain about how to tell if the string is null-terminated. QString and QByteArray don't null-terminate and strlen(...) doesn't count the null-character. Suggestions?

But like i said earlier, i'm fairly certain the library ensures the buffer is filled correctly.

marcel
17th June 2008, 10:54
if it segfaults where you said it does then it certainly must be something wrong with the buffer.
is the library running any additional thread(s)?

anyway, this situation is very common to buffer overruns (because of the non-null terminated string, in QString::operator=).
sometimes it crahses because it attempts to read memory beyond the limits of the buffer, allocated by other objects.

marcel
17th June 2008, 10:59
Actually, I think the crash in QString::operator = occurs when returning the QString.
Just for curiosity, can you try:


qstrValue = QString::fromAscii(cstr);

instead of what you have now?

I'm too lazy to take a look in the QString(const char*) constructor now... Oh, and a lot of work to do too :).

marcel
17th June 2008, 11:04
Actually, I think the crash in QString::operator = occurs when returning the QString.
Just for curiosity, can you try:


qstrValue = QString::fromAscii(cstr);
instead of what you have now?

I'm too lazy to take a look in the QString(const char*) constructor now... Oh, and a lot of work to do too :).
neah, that's not it :).

TheRonin
17th June 2008, 12:02
yeah, the char* constructor and the operator= method both result in calls to fromAscii().

I suspected that the QByteArray solution should have worked and also that it didn't because i hadn't replaced all the calls to Get_Value, and some earlier call might have been the actual cause of the crash. So now i'm using QByteArray everywhere and it seems to be working, but on the other hand, it might just be dumb luck because the QString solution was working most of the time earlier as well.

Having taken a look at the code for QString i can't find that it copies the buffer at any time. I've followed the code to a call to a method called iconv(..) but the specification of iconv (http://www.opengroup.org/onlinepubs/007908775/xsh/iconv.html) doesn't explicitly say that a copy is performed. This leads me to believe that using QByteArray must be the only safe route since it explicitly performs a deep copy.

What do you think?

TheRonin
19th June 2008, 13:20
I looked more closely at the QString code and found that it indeed performs a deep copy after all. My mistake. I ran my binary through Valgrind and it complained about an illegal write at the strangest place; setting a private integer class member to 0. The problem simply must lie elsewhere. I'm beginning to suspect my make system since it keeps whining about clock skew. Maybe i'm getting a strange build as a result.

Thanks for your help marcel.