Почему _beginthreadex завершается ошибкой с ERROR_INVALID_ACCESS?

0

У меня есть куча QWebViews, отображаемая на виджет. Наступает момент, когда я начинаю получать ошибку QThread::start: Failed to create thread (The access code is invalid.). Глядя на источник Qt, кажется, что _beginthreadex возвращает пустой дескриптор, а errno - ERROR_INVALID_ACCESS, но я понятия не имею, почему.

Вот обратная сторона при печати ошибки:

0   qErrnoWarning                           qglobal.cpp    2451    0x69ccdd3c  
1   QThread::start                          qthread_win.cpp 469 0x69cd5831  
2   QThreadPoolPrivate::tryStart            qthreadpool.cpp 203 0x69ccc3f5  
3   QThreadPool::start                      qthreadpool.cpp 474 0x69cccdf4  
4   QHostInfoLookupManager::work            qhostinfo.cpp   633 0x6cb9b071  
5   QHostInfoLookupManager::scheduleLookup  qhostinfo.cpp   652 0x6cb9b143  
6   QHostInfo::lookupHost                   qhostinfo.cpp   202 0x6cb9a220  
7   qt_qhostinfo_lookup                     qhostinfo.cpp   722 0x6cb9b4b6  
8   QAbstractSocket::connectToHostImplementation    qabstractsocket.cpp 1427    0x6cbb17f5  
9   QAbstractSocket::qt_static_metacall     moc_qabstractsocket.cpp 166 0x6cbb4925  
10  QMetaMethod::invoke                     qmetaobject.cpp 1664    0x69dc784f  
11  QMetaObject::invokeMethod               qmetaobject.cpp 1179    0x69dc6d6b  
12  QMetaObject::invokeMethod               qobjectdefs.h   418 0x6cd361dd  
13  QAbstractSocket::connectToHost          qabstractsocket.cpp 1342    0x6cbb13b3  
14  QSslSocket::connectToHostImplementation qsslsocket.cpp  1744    0x6cbc7340  
15  QSslSocket::qt_static_metacall          moc_qsslsocket.cpp  91  0x6cbc93cf  
16  QMetaMethod::invoke                     qmetaobject.cpp 1664    0x69dc784f  
17  QMetaObject::invokeMethod               qmetaobject.cpp 1179    0x69dc6d6b  
18  QMetaObject::invokeMethod               qobjectdefs.h   418 0x6cd361dd  
19  QAbstractSocket::connectToHost          qabstractsocket.cpp 1342    0x6cbb13b3  
20  QSslSocket::connectToHostEncrypted      qsslsocket.cpp  422 0x6cbc55e1  
21  QHttpNetworkConnectionChannel::ensureConnection qhttpnetworkconnectionchannel.cpp   607 0x6cb6191f  
22  QHttpNetworkConnectionPrivate::_q_startNextRequest  qhttpnetworkconnection.cpp  862 0x6cb5e92c  
23  QHttpNetworkConnectionPrivate::queueRequest qhttpnetworkconnection.cpp  501 0x6cb5c57d  
24  QHttpNetworkConnection::sendRequest     qhttpnetworkconnection.cpp  931 0x6cb5edf2  
25  QHttpThreadDelegate::startRequest       qhttpthreaddelegate.cpp 291 0x6cb8912a  
26  QHttpThreadDelegate::qt_static_metacall moc_qhttpthreaddelegate_p.cpp   113 0x6cbd147c  
27  QMetaCallEvent::placeMetaCall           qobject.cpp 525 0x69dcf91c  
28  QObject::event                          qobject.cpp 1195    0x69dd08db  
29  QApplicationPrivate::notify_helper      qapplication.cpp    4551    0x2582f44   
30  QApplication::notify                    qapplication.cpp    3933    0x25808b7   
31  QCoreApplication::notifyInternal        qcoreapplication.cpp    915 0x69dc0dc6  
32  QCoreApplication::sendEvent             qcoreapplication.h  231 0x69e35185  
33  QCoreApplicationPrivate::sendPostedEvents   qcoreapplication.cpp    1539    0x69dc1d2a  
34  qt_internal_proc                        qeventdispatcher_win.cpp    496 0x69de2590  
35  USER32!OffsetRect                       C:\Windows\syswow64\user32.dll  0   0x74cc62fa  
36  ??      0   0x152404    
37  ??      0   0x401   
38  ??      0       

Код при вызове выглядит так:

d->handle = (Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start, //d->stackSize is 0
                                            this, CREATE_SUSPENDED, &(d->id));

if (!d->handle) {
    qErrnoWarning(errno, "QThread::start: Failed to create thread");
    d->running = false;
    d->finished = true;
    return;
}

Почему это происходит и как я могу это исправить?

EDIT: также следует отметить, что ровно 500 потоков в точке, в которой это происходит.

Теги:
multithreading
qt

1 ответ

4
Лучший ответ

Хорошая вероятность того, что у вас закончилось свободное адресное пространство вашего процесса (для стеков потоков) после создания 500 потоков. В 32-разрядной Windows процессы получают только 2 ГБ адресного пространства по умолчанию (верхняя половина адресного пространства зарезервирована для ядра). 500 1MB стеков потоков (размер по умолчанию, Qt может идти выше или ниже) плюс все другие распределения, которые ваш процесс делает, могут легко использовать это.

Смотрите эту статью Old New Thing для получения дополнительной информации.

Возможные исправления:

  1. Если вы знаете, что ваши QThreads не нужны очень большие стеки, вы можете вызвать QThread :: setStackSize(), чтобы установить меньший размер перед началом потока.
  2. Подумайте об использовании пула потоков и/или просто уменьшите количество запущенных параллельных потоков. Маловероятно, что у вас достаточно процессорных ядер, чтобы сделать 500+ потоки продуктивными.
  3. Используйте переключатель Windows/3GB и сделайте свое приложение LARGE ADDRESS AWARE, чтобы получить 3 ГБ адресного пространства пользовательского режима.
  4. Go 64-bit (для 63 бит адресного пространства пользовательского режима).
  • 0
    Интересно, я не думал, что это будет проблемой, так как диспетчер задач сообщает, что процесс использует только ~ 600 МБ памяти. GDB использует 522 МБ. Что касается # 1 и # 2 ваших возможных исправлений, как вы можете видеть, мой код не знает об этих потоках, так как они созданы самим Qt. Я думаю, я могу либо выяснить, почему потоки не завершаются, либо увидеть около 64 бит.
  • 0
    Зарезервированное адресное пространство не обязательно должно быть поддержано памятью, поэтому, если потоки не используют много стека, вы можете не увидеть, что значение «Использование памяти» слишком высоко в Диспетчере задач, но ваш процесс может по-прежнему заканчиваться адресное пространство. Попробуйте отобразить столбец «Размер виртуальной машины» в диспетчере задач, чтобы получить лучшее изображение.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню