QString toUtf8() 中的崩溃
Crash in QString toUtf8()
我有空位:
void Foo::func(QString str1, const QString& str2, int width, int height)
{
std::unique_lock<std::mutex> _lock(m_mutex);
#ifdef _DEBUG
MEMORYSTATUSEX statex;
statex.dwLength = sizeof (statex);
if (GlobalMemoryStatusEx(&statex)) {
qDebug() << QString("There are %1 free MB of physical memory.\n").arg(statex.ullAvailPhys / 1024 / 1024);
}
#endif
BaseClass::someFunc(
str1.toStdString(),
str2.toUtf8().constData(),
width,
height
);
}
似乎是正确的,而且有效。但是,如果程序运行了很长时间(例如晚上),它会在第
行的此函数中崩溃
str2.toUtf8().constData()
我最初以为这是一个基于线程的错误,但我的锁没有起作用。所有局部变量和 class 成员都可以。崩溃错误是:
First-chance exception at 0x76E45B68 foo.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x00EFC6EC
但是从上面的代码最后 MEMORYSTATUSEX 显示可用内存是
There are 2314 free MB of physical memory
我还认为 str2 太大了,但它在 49152、168441 等长度下工作正常。问题是什么?我错过了什么吗?
堆栈跟踪:
KernelBase.dll!_RaiseException@16() Unknown
[External Code]
Qt5Cored.dll!qBadAlloc() Line 2849 C++
Qt5Cored.dll!QByteArray::QByteArray(int size, Qt::Initialization __formal) Line 1409 C++
Qt5Cored.dll!QUtf8::convertFromUnicode(const QChar * uc, int len) Line 151 C++
Qt5Cored.dll!QString::toUtf8_helper(const QString & str) Line 4373 C++
Qt5Cored.dll!QString::toUtf8() Line 56 C++
foo.exe!Foo::func(QString str1, const QString & str2, int width, int height) Line 3600 C++
foo.exe!Foo::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 1126 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender, int signalOffset, int local_signal_index, void * * argv) Line 3717 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Line 3582 C++
foo.exe!SomeClass::func(QString _t1, const QString & _t2, int _t3, int _t4) Line 137 C++
foo.exe!SomeClass::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 81 C++
Qt5Cored.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 485 C++
Qt5Cored.dll!QObject::event(QEvent * e) Line 1246 C++
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3720 C++
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3164 C++
Qt5Cored.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 935 C++
Qt5Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 228 C++
Qt5Cored.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1552 C++
Qt5Cored.dll!QCoreApplication::sendPostedEvents(QObject * receiver, int event_type) Line 1410 C++
qwindowsd.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 81 C++
Qt5Cored.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned int wp, long lp) Line 414 C++
[External Code]
Qt5Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 807 C++
qwindowsd.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 73 C++
Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 129 C++
Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 204 C++
Qt5Cored.dll!QCoreApplication::exec() Line 1188 C++
Qt5Guid.dll!QGuiApplication::exec() Line 1508 C++
Qt5Widgetsd.dll!QApplication::exec() Line 2957 C++
foo.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * lpCmdLine, int __formal) Line 348 C++
[External Code]
提前致谢!
对于那些像我一样偶然发现这个线程的人,因为他们想通过调用 str.toUtf8().constData()
或 str.toUtf8().data()
将 QString
转换为 char *
,但这会导致程序崩溃或在 XCode 上抛出类似 EXC_BAD_ACCESS
的异常,答案如下:
- 在像
foo = str.toUtf8().constData();
这样的调用中,str.toUtf8()
部分创建了一个临时对象。
- 对
tmp.data()
或 tmp.constData()
的调用 return 指向由对象本身管理的内部缓冲区的指针,其生命周期与临时对象的生命周期相关联。 source.
- 一旦该语句被执行,其地址被分配给
foo
的对象的生命周期,一旦 return 被 data()
或 constData()
编辑,将结束。
- 因此,正如预期的那样,在该语句之后
foo
将保存一个生命周期结束的对象的地址,从而导致崩溃和异常。
我有空位:
void Foo::func(QString str1, const QString& str2, int width, int height)
{
std::unique_lock<std::mutex> _lock(m_mutex);
#ifdef _DEBUG
MEMORYSTATUSEX statex;
statex.dwLength = sizeof (statex);
if (GlobalMemoryStatusEx(&statex)) {
qDebug() << QString("There are %1 free MB of physical memory.\n").arg(statex.ullAvailPhys / 1024 / 1024);
}
#endif
BaseClass::someFunc(
str1.toStdString(),
str2.toUtf8().constData(),
width,
height
);
}
似乎是正确的,而且有效。但是,如果程序运行了很长时间(例如晚上),它会在第
行的此函数中崩溃str2.toUtf8().constData()
我最初以为这是一个基于线程的错误,但我的锁没有起作用。所有局部变量和 class 成员都可以。崩溃错误是:
First-chance exception at 0x76E45B68 foo.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x00EFC6EC
但是从上面的代码最后 MEMORYSTATUSEX 显示可用内存是
There are 2314 free MB of physical memory
我还认为 str2 太大了,但它在 49152、168441 等长度下工作正常。问题是什么?我错过了什么吗?
堆栈跟踪:
KernelBase.dll!_RaiseException@16() Unknown
[External Code]
Qt5Cored.dll!qBadAlloc() Line 2849 C++
Qt5Cored.dll!QByteArray::QByteArray(int size, Qt::Initialization __formal) Line 1409 C++
Qt5Cored.dll!QUtf8::convertFromUnicode(const QChar * uc, int len) Line 151 C++
Qt5Cored.dll!QString::toUtf8_helper(const QString & str) Line 4373 C++
Qt5Cored.dll!QString::toUtf8() Line 56 C++
foo.exe!Foo::func(QString str1, const QString & str2, int width, int height) Line 3600 C++
foo.exe!Foo::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 1126 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender, int signalOffset, int local_signal_index, void * * argv) Line 3717 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Line 3582 C++
foo.exe!SomeClass::func(QString _t1, const QString & _t2, int _t3, int _t4) Line 137 C++
foo.exe!SomeClass::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 81 C++
Qt5Cored.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 485 C++
Qt5Cored.dll!QObject::event(QEvent * e) Line 1246 C++
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3720 C++
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3164 C++
Qt5Cored.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 935 C++
Qt5Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 228 C++
Qt5Cored.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1552 C++
Qt5Cored.dll!QCoreApplication::sendPostedEvents(QObject * receiver, int event_type) Line 1410 C++
qwindowsd.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 81 C++
Qt5Cored.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned int wp, long lp) Line 414 C++
[External Code]
Qt5Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 807 C++
qwindowsd.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 73 C++
Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 129 C++
Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 204 C++
Qt5Cored.dll!QCoreApplication::exec() Line 1188 C++
Qt5Guid.dll!QGuiApplication::exec() Line 1508 C++
Qt5Widgetsd.dll!QApplication::exec() Line 2957 C++
foo.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * lpCmdLine, int __formal) Line 348 C++
[External Code]
提前致谢!
对于那些像我一样偶然发现这个线程的人,因为他们想通过调用 str.toUtf8().constData()
或 str.toUtf8().data()
将 QString
转换为 char *
,但这会导致程序崩溃或在 XCode 上抛出类似 EXC_BAD_ACCESS
的异常,答案如下:
- 在像
foo = str.toUtf8().constData();
这样的调用中,str.toUtf8()
部分创建了一个临时对象。 - 对
tmp.data()
或tmp.constData()
的调用 return 指向由对象本身管理的内部缓冲区的指针,其生命周期与临时对象的生命周期相关联。 source. - 一旦该语句被执行,其地址被分配给
foo
的对象的生命周期,一旦 return 被data()
或constData()
编辑,将结束。 - 因此,正如预期的那样,在该语句之后
foo
将保存一个生命周期结束的对象的地址,从而导致崩溃和异常。