Return QString from function - thread safe?

I'm new to Qt, but this could be a very simple C ++ problem. I have a simple function that returns a QString:

QString testclass::myfunc(int i)
{
    QString result;
    switch (i) {
    case 1: result = "one"; break;
    case 2: result = "two"; break;
    }
    return result;
}

      

It's safe? Does the c compiler guarantee the return value stays in memory long enough to be used by the calling function? (Or it could damage the memory). If the latter, what's the correct way to return a QString? (Should the result of var be static? Should the result be a member of var testclass?)

Does it matter that QString contains constants? (What case id 3 assigned the result to a random string)

What if myfunc is a static method that I want to call from different threads? Do I have to pass an additional Qstring by reference so that each caller gets its own variable (and returns empty)?


Here is the actual function (bit cleared) - and note that this function is STATIC in case it matters:

QString L::toString(const L::editions &level)
{
    QString levelStr;
    switch (level) {
        case L::one:
            levelStr = "one";
            break;
        case L::two:
            levelStr = "two";
            break;
        case L::three:
            levelStr = "thre";
            break;
        default:
            levelStr = "Internal Error";
            break;
    }
    return levelStr;
}

      

and still valgrind complains (line 121 - 'levelStr = "one";')

34 bytes in 1 blocks are definitely lost in loss record 197 of 716
  in L::toString(L::edition const&) in /mnt/lserver2/data/development/haast/src/linfo.cpp:121
  1: malloc in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so
  2: QArrayData::allocate(unsigned long, unsigned long, unsigned long, QFlags<QArrayData::AllocationOption>) in /opt/Qt/5.3/gcc_64/lib/libQt5Core.so.5.3.1
  3: QString::QString(int, Qt::Initialization) in /opt/Qt/5.3/gcc_64/lib/libQt5Core.so.5.3.1
  4: /opt/Qt/5.3/gcc_64/lib/libQt5Core.so.5.3.1
  5: QString::fromUtf8_helper(char const*, int) in /opt/Qt/5.3/gcc_64/lib/libQt5Core.so.5.3.1
  6: QString::fromUtf8(char const*, int) in <a href="file:///opt/Qt/5.3/gcc_64/include/QtCore/qstring.h:492" >/opt/Qt/5.3/gcc_64/include/QtCore/qstring.h:492</a>
  7: QString::operator=(char const*) in <a href="file:///opt/Qt/5.3/gcc_64/include/QtCore/qstring.h:609" >/opt/Qt/5.3/gcc_64/include/QtCore/qstring.h:609</a>
  8: L::toString(L::Lconst&amp;) in <a 

      

+3


source to share


2 answers


http://qt-project.org/doc/qt-5/qstring.html#details

The QString class provides a string of Unicode characters.

QString stores a string of 16-bit QChars, where each QChar corresponds to one Unicode 4.0 character. (Unicode characters with code values ​​higher than 65535 are stored using surrogate pairs, i.e. Two consecutive QChars.)

Unicode is the international standard that supports most of the writing systems in use today. It is a superset of US-ASCII (ANSI X3.4-1986) and Latin-1 (ISO 8859-1), and all US-ASCII / Latin-1 characters are available at the same code positions.

Behind the scenes, QString uses implicit sharing (copy-on-write) to reduce memory usage and avoid unnecessary copying of data. It also helps reduce the storage overhead of 16-bit characters instead of 8-bit characters.

In addition to QString, Qt also provides a QByteArray class for storing raw bytes and traditional 8-bit strings with "\ 0". For most purposes, QString is the class you want to use. It is used throughout Qt's APIs and Unicode support ensures that your applications are easy to translate if you want to expand your application market at some point. The two main cases when QByteArray are appropriate when you need to store raw binary data and when memory retention is critical (for example, in embedded systems).

Basically, QString is awesome and almost light-hearted. You can use it anywhere and you like it. If you linger too often from adding strings, there is a special way to use the string builder, but in my experience there are many other places for improvement before trying to make QString better.

And to answer your questions directly:

It's safe? Does the c compiler guarantee the return value stays in memory long enough to be used by the calling function? (Or it could damage the memory). If the latter, what's the correct way to return a QString? (Should the result of var be static? Should the result be a member of var testclass?)

In all of the above cases mentioned above, it is safe. General pointers, etc. Store it in memory as long as any function has a QString handle. Once he is completely out of scope, he is purified.

Does it matter that QString contains constants? (What case id 3 assigned the result to a random string)



No, it doesn't matter.

What if myfunc is a static method that I want to call from different threads? Do I have to pass an additional Qstring by reference so that each caller gets its own variable (and returns empty)?

You have to wrap it with cross thread protectors, for example QMutexLocker

.

UPDATE: QMutexLocker example

// In your constructor

m_mutex = new QMutex();


// When accessing a shared element across threads

{
    QMutexLocker locker(m_mutex);
    // Accessing a variable is now threadsafe!
    m_sharedDataString += "!";
}

      

Hope it helps.

+5


source


QString

is a value class, it would be useless if you couldn't return it from a function. Here is nothing else than std::string

. Both can be used the way you are demonstrating.

The "const string" concept you call is imaginary. There is no such thing. The operator result = "foo";

does not create a string that is somehow special. It's not C, you're not returning const char *

- and for a good reason.

The thread safety aspect has nothing to do with strings. The body of the method you are showing can be a static method since it doesn't use instance data. It is also a pure function that has no access to any shared state at all. Such pure functions are thread safe by definition because they don't have access to shared state. You might want to revisit your question with an example that is closer to your problem, and actually demonstrates some threading issues.



QString

Like other Qt implicitly shared class classes, it is thread safe if a specific instance of that object is accessible from only one thread. It doesn't matter if the instance may have been assigned or copied from another instance of the string. For example:

QString a = "foo";
{
  QFutureSynchronizer sync;
  sync.addFuture(QtConcurrent::run([&a] { a.append("bar"); }));
  sync.addFuture(QtConcurrent::run([&a] { a.append("baz"); }));
}
// This is not thread safe: a might be concurrently accessed from two
// threads. The behavior is undefined. It might format your hard drive.

QString c = "Homer";
QString d = c;
{
  QFutureSynchronizer sync;
  sync.addFuture(QtConcurrent::run([&c] { c.append("'s"); }));
  sync.addFuture(QtConcurrent::run([&d] { d.append(" and Elmer's"; }));
}
// This is thread safe. One of the threads will safely deep-copy the
// c contents.
Q_ASSERT(c == "Homer's");
Q_ASSERT(d == "Homer and Elmer's");

      

+1


source







All Articles