Qt 中经常会使用 QString::toUtf8()
获取字符串的 UTF-8 数组,例如下面这样使用:
1 2 3 4
| void foo(const char *data) { ... }
const char *data = QString::toUtf8().constData(); foo(data);
|
看上去没啥问题,其实这个代码有很严重的问题,一般不是经验很丰富的程序员很难发现这个 Bug,很可能会导致程序崩溃退出,但就是找不到为什么。这是因为 QString::toUtf8()
返回的是一个 QByteArray 的栈变量,第 3 行语句中的 QByteArray 是一个临时变量,这行语句结束时这个变量就被析构了,指针 data 指向的内存也被回收,所以下面使用的 data 指向的内存已经被释放了,难怪程序会崩溃了。把代码修改为下面的样子则就能够正确运行了:
1 2 3 4 5 6 7
| foo(QString::toUtf8().constData());
QByteArray ba = QString::toUtf8(); const char *data = ba.constData(); foo(data);
|
这个问题涉及到临时变量的析构,也许还不太明白是怎么回事,下面的程序就来模拟上面的情况,一看就明白了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include <QDebug>
class B { public: B() { qDebug() << "B()"; }
~B() { qDebug() << "~B()"; }
int value = 10; };
class A { public: A() { qDebug() << "A()"; b = new B(); }
~A() { delete b; qDebug() << "~A()"; }
B *b = nullptr; };
A a() { return A(); }
void foo(B *b) { qDebug() << b->value; }
int main(int argc, char** argv) { foo(a().b);
B *b = a().b; qDebug() << b->value;
qDebug() << "main() 结束"; return 0; }
|
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13
| A() B() 10 ~B() ~A()
A() B() ~B() ~A() 1859919056 // 注意: 这里不是 10 呢
main() 结束
|