我有一个程序,其中使用new运算符创建QApplication.它因未知原因而崩溃.我使用RedHat Linux,G 4.8.2,Qt 4.7.2,它是用相同的编译器构建的.
这个源包含许多看似无用但无害的部分,例如带有四个未使用参数的’func’函数.如果我试图删除它们并进一步简化程序,则崩溃不再可以再现,这当然并不意味着问题已经解决.
崩溃发生在函数strlen中,该函数从系统函数XSetCommand调用.添加我自己的简单实现允许我看到strlen收到一个损坏的指针,见下文.
#include Box>
void func(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());
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
如你所见,它发生在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有一个特殊的(和IMHO可疑的)要求.见documentation:
Warning: The data referred to by argc and argv must stay valid for the entire lifetime of the QApplication object. In addition,argc must be greater than zero and argv must contain at least one valid character string.
如果argc和argv在运行时被销毁,则会发生未定义的行为.它可能在某些平台上运行,并且会在其他平台上崩溃.相应地更改您的代码并检查它是否修复了您的问题.