[英]Segmentation fault when Qt QApplication created with new
我有一個程序,其中 QApplication 是使用 new 運算符創建的。 它因未知原因崩潰。 我使用使用相同編譯器構建的 RedHat Linux、G++ 4.8.2、Qt 4.7.2。
該源代碼包含許多看起來無用但無害的部分,例如帶有四個未使用參數的“func”函數。 如果我嘗試刪除它們並進一步簡化程序,則無法再重現崩潰,這當然並不意味着問題已解決。
崩潰發生在從系統函數 XSetCommand 調用的函數 strlen 中。 添加我自己的簡單實現讓我看到 strlen 收到一個損壞的指針,見下文。
#include <QApplication>
#include <QMessageBox>
void func(void *, void *, void *, void *) {}
struct Gui
{
QApplication qApplication;
Gui(int argc, char ** argv) : qApplication(argc, argv) {}
};
struct Process
{
Process(const std::string &, int argc, char ** argv) {
func(ptr(), ptr(), ptr(), ptr());
std::string recent;
std::string path = std::string("Hi!");
recent = std::string("Hi!");
m_message = std::string("Hi!");
m_gui = new Gui(argc, argv);
}
~Process() { delete m_gui; }
int exec(void) {
return QMessageBox::warning(0, "Exit", "Sure?", QMessageBox::Ok);
}
void * ptr(void) { return 0; }
Gui * m_gui;
std::string m_message;
};
std::size_t strlen(const char * p) {
std::size_t s = 0;
while (*p++)
s++;
return s;
}
int main(int argc, char ** argv) {
Process process("SomeString", argc, argv);
return process.exec();
}
崩潰回溯:
#0 0x0000000000400f13 in strlen (p=0x11 <Address 0x11 out of bounds>) at /home/alex/test/megaCrash/myprog.cpp:39
#1 0x0000003880a41922 in XSetCommand () from /usr/lib64/libX11.so.6
#2 0x0000003880a45fa6 in XSetWMProperties () from /usr/lib64/libX11.so.6
#3 0x00002aaaaad2e5ea in QWidgetPrivate::create_sys(unsigned long, bool, bool) () from /usr/local/Trolltech/Qt-4.7.2/lib/libQtGui.so.4
#4 0x00002aaaaace735d in QWidget::create(unsigned long, bool, bool) () from /usr/local/Trolltech/Qt-4.7.2/lib/libQtGui.so.4
#5 0x00002aaaaacef73a in QWidget::setVisible(bool) () from /usr/local/Trolltech/Qt-4.7.2/lib/libQtGui.so.4
#6 0x00002aaaab11de5e in QDialog::setVisible(bool) () from /usr/local/Trolltech/Qt-4.7.2/lib/libQtGui.so.4
#7 0x00002aaaab11d9e6 in QDialog::exec() () from /usr/local/Trolltech/Qt-4.7.2/lib/libQtGui.so.4
#8 0x00002aaaab13bb40 in ?? () from /usr/local/Trolltech/Qt-4.7.2/lib/libQtGui.so.4
#9 0x00002aaaab13bc7f in QMessageBox::warning(QWidget*, QString const&, QString const&, QFlags<QMessageBox::StandardButton>, QMessageBox::StandardButton) () from /usr/local/Trolltech/Qt-4.7.2/lib/libQtGui.so.4
#10 0x0000000000401514 in Process::exec (this=0x7fffffffe4e0) at /home/alex/test/megaCrash/myprog.cpp:27
#11 0x0000000000400fb6 in main (argc=1, argv=0x7fffffffe5f8) at /home/alex/test/megaCrash/myprog.cpp:47
如您所見,它發生在 strlen 中。 這就是為什么我包含我自己的實現。 它的論點 p 沒有指向任何地方。 我試圖用 Qt 的調試版本來重現它 - 沒有運氣。 這一切讓我覺得這里有一個令人討厭的內存損壞。 但它可能發生在哪里? 我在這里只做無辜的事情。
我使用 CMake 來構建它:
cmake_minimum_required (VERSION 2.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-local-typedefs -fpic -fvisibility=hidden -m64")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -DDEBUG -gdwarf-2 -fstack-protector-all")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs")
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
find_package(Qt4 REQUIRED)
include(${QT_USE_FILE})
add_executable(myprog myprog.cpp)
target_link_libraries(myprog ${QT_LIBRARIES})
我試圖在 Qt 文檔和互聯網中找到提示 - 沒有運氣。 謝謝
QApplication
對argc
和argv
有一個特殊的(恕我直言有問題)要求。 請參閱文檔:
警告: argc 和 argv 引用的數據必須在 QApplication 對象的整個生命周期內保持有效。 此外,argc 必須大於零且 argv 必須包含至少一個有效字符串。
如果argc
和argv
在運行時被破壞,則會發生未定義的行為。 它可能在某些平台上工作,而在其他平台上會崩潰。 相應地更改您的代碼並檢查它是否可以解決您的問題。
我遇到了同樣的問題並實現了以下類來持久化命令行參數:
。H:
#pragma once
#include <string>
#include <vector>
using std::string;
using std::vector;
class PersistentArgs
{
protected:
vector<string> mArgStrs;
public:
int mArgc;
vector<char*> mArgv;
PersistentArgs() = delete;
PersistentArgs(int argc, char* argv[]);
virtual ~PersistentArgs();
};
.cpp:
#include "PersistentArgs.h"
PersistentArgs::PersistentArgs(int argc, char* argv[])
{
mArgc = argc;
for (int i = 0; i < argc; i++)
{
string arg(argv[i]);
mArgStrs.push_back (arg);
}
for (int i = 0; i < argc; i++)
{
mArgv.push_back ((char*)mArgStrs[i].c_str());
}
mArgv.push_back (nullptr);
}
PersistentArgs::~PersistentArgs()
{
mArgv.clear();
mArgStrs.clear();
}
用法:
PersistentArgs* args;
void atStart (int argc, char* argv[])
{
args = new PersistentArgs (argc, argv);
QApplication* qtApp = new QApplication (args->mArgc, &args->mArgv[0]);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.