Getting char * from Qstring gives garbage [duplicate] - qt

I have a weird problem:
QString s1="abc";
const char * ss1=s1.toUtf8().constData();
QString s2=QString::fromUtf8(ss1);
if(s1==s2)
qDebug()<<"s1==s2";
else
qDebug()<<"s1!=s2";
The output of the above code is "s1!=s2". In fact, the content of ss1 and s2 is a mess. But the output of the following code is "s1==s2". Why?
QString s1="abc";
QString s2=QString::fromUtf8(s1.toUtf8().constData());
if(s1==s2)
qDebug()<<"s1==s2";
else
qDebug()<<"s1!=s2";

Because you have undefined behavior in your code:
const char * ss1 = s1.toUtf8().constData();
The QByteArray returned by the toUtf8() function is a temporary object and is destroyed. But you are keeping a pointer to its data which you then try to use:
QString s2=QString::fromUtf8(ss1);
This results in undefined behavior.
For this to work, you need to keep the temporary QByteArray object alive. You can use a const reference for that. It will extend the life of the temporary object:
QString s1 = "abc";
const auto& bytes = s1.toUtf8();
const char * ss1 = bytes.constData();
Your second example is fine, because you are not using any pointers to internal memory of destroyed objects:
QString s2 = QString::fromUtf8(s1.toUtf8().constData());
The temporary QByteArray object returned by toUtf8() is only destroyed after the call to fromUtf8() returns. So the constData() pointer is valid for long enough to allow the function to read the data.

Related

How to get correct QString from "\u0000"?

Sometimes I receive QString with value "\u0000" and I want to check if the received string equals to "\u0000".
But when I try:
qDebug() << QString("\u0000") << QString::fromUtf8("\u0000");
I get output: "\u0001" "\u0001"
So as a result I can not compare the strings. I see that initially this string was created using snprintf from byte to get char* and then created std::string and QString from std::string, but I can't reproduce it so far actually. But I feel like this is a workaround, but not the easy way to do it.
How do I create QString with value \u0000 using QString API and why QString("\u0000") results in value "\u0001"?
QString is always null-terminated. A null QString means that it has no data in its internal array but an empty QString has a single null character in its internal data array. So, if you have any control over the sender of the original array, it is better to send it by a QByteArray instead of a QString. You won't be able to count multiple null characters in a QString.
From QString reference document:
QString().isNull(); // returns true
QString().isEmpty(); // returns true
QString("").isNull(); // returns false
QString("").isEmpty(); // returns true
QString("abc").isNull(); // returns false
QString("abc").isEmpty(); // returns false
I figured out how to create such a string.
QString str(1, QChar('\0'));
or from std::string:
QString::fromStdString(std::string("\0", 1));
But I still don't know why QString("\u0000") results in "\u0001"

How to read an unsigned int from a std::unique_ptr<unsigned char[]>?

So basically I'm working on a file reader and the binary file gets loaded into a std::unique_ptr<unsigned char[]> containing all the bytes from the file.
I'm trying to read an unsigned int from the start of it. Usually, if it were just a raw pointer (unsigned char*) it would be as follows:
unsigned int magic = *(reinterpret_cast<unsigned int*>(buffer));
However, I'm currently trying to the same, where buffer is the smart pointer. So far I've came up with this:
unsigned int magic = *(reinterpret_cast<unsigned int*>(classFile_.get()));
Upon outputting magic like this:
std::cout << std::hex << magic;
I get 1. Where I should be getting: 0xbebafeca (this is a Java class file reader, 0xCAFEBABE is the unsigned int magic number).
Any ideas as to why it's not working? I'm also not sure if storing a smart pointer for the unsigned char* is good practice rather than doing something like storing a raw pointer and deleting the allocated array in the de-constructor.

How to convert QList<QByteArray> to QString in QT?

I have a QList<QByteArray> that I want to print out in a QTextBrowser. QTextBrowser->append() takes a QString.
Despite a ton of searching online, I have not found a way to convert the data I have into a QString.
There are several functions to convert QByteArray to QString: QString::fromAscii(), QString::fromLatin1(), QString::fromUtf8() etc. for the most common ones, and QTextCodec for other encodings. Which one is the correct one depends on the encoding of the text data in the byte array.
Try:
for(int i=0; i<list.size(); ++i){
QString str(list[i].constData());
// use your string as needed
}
from QByteArray to QString, do
const char * QByteArray::constData () const
Returns a pointer to the data stored in the byte array. The pointer
can be used to access the bytes that compose the array. The data is
'\0'-terminated. The pointer remains valid as long as the byte array
isn't reallocated or destroyed.
This function is mostly useful to pass a byte array to a function that
accepts a const char *.
you then have this QString constructor
QString ( const QChar * unicode )

Storing a char in a char pointer

I have a global variable that is a *char. My main function header reads as int main(int argc, char* argv[argc]){...}. These two lines of code have to remain the way they are. The first argument of my main function is a number of type *char, that I convert to a char using atoi(...);. I am basically changing the ASCII value to its corresponding character. Now I want to store this local variable character I have into the global variable that is a char pointer. I know the problem is related to allocation of memory, but I am not sure how to go about this.
My code:
char* delim;
int main(int argc, char* argv[argc])
{
char delimCharacter;
if (isdigit(*(argv[3])) == 0) delim = argv[3]; //you can pass in a character or its ascii value
else { //if the argument is a number, then the ascii value is taken
delimCharacter = atoi((argv[3]));
printf("%s\t,%c,\n", argv[3], delimCharacter);
//sprintf( delim, "%c", delimCharacter ); // a failed attempt to do this
*delim = delimCharacter;
//strncpy(delim, delimCharacter, 1); // another failed attempt to do this
}
//printf("%s\n",delim);
This yields a seg fault.
You need to verify you have got (at least) 3 arguments before you start using them.
if (argc < 4)
{
printf("Need 3 args");
exit(1);
}
Then you need to allocate some memory to put the character in.
delim = malloc(2);
// TODO: Should check the result of malloc before using it.
*delim = delimCharacter;
delim[1] = 0; // Need to NULL terminate char*
You're dereferencing an uninitialized pointer. delim never gets initialized when it goes into the else block.
char delim[] = ","; // anything really, as long as as it's one character string
...
delim[0] = delimCharacter;
In addition to your memory issue, I think you are confused about what atoi does. It parses a string representation of a number and returns the equivalent int value, e.g. "10000" => 10,000. I think that you think it will give you the ASCII value of a character, e.g. "A" =>65.
Since you have a char *, and you are (I think) assuming that it contains a single character, you could simply do this:
delimCharacter = *(argv[3]);
However, there really seems to be no need to use the intermediate step of assigning this value to a char variable at all. If the end goal is to have delim point to the char that is the delimiter, then it seems this is all you need to do:
delim = argv[3];
Not only does this remove unnecessary code, but it means you would no longer need to allocate additional memory for delim to point to.
I would also declare delim as a const char * since I assume there is no reason to change it.

Very big QImage and Memory Mapped Files in QT

I want bind QImage to the MMF file to manipulate the image without the cost of memory directly on the disc. Unfortunately, my code creates a copy in memory.
QFile file("Boston City Flow.jpg");
if(!file.open(QIODevice::ReadOnly))
QMessageBox::information(this, "Error", "Error");
qint64 size = file.size();
unsigned char *mmf = file.map(0, size);
QImage image;
image.loadFromData(mmf, size, NULL);
My program needs to handle very large images.
Try with declaring mmf const:
const unsigned char* mmf = file.map(0, size);
and then have a look at the QImage ctors, especially
QImage( const uchar*, int width, int height, Format )
QImage::QImage ( const uchar * data, int width, int height, Format format )
The docs say:
"The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer. The image does not delete the buffer at destruction.
[...]
Unlike the similar QImage constructor that takes a non-const data buffer, this version will never alter the contents of the buffer. For example, calling QImage::bits() will return a deep copy of the image, rather than the buffer passed to the constructor. This allows for the efficiency of constructing a QImage from raw data, without the possibility of the raw data being changed."
Note that the non-const uchar* version copies the right away, so make sure to pass a const uchar*. Also note that calling non-const methods of QImage will copy the data.

Resources