有关Qt的一些记录
本文于1040天之前发表,文中内容可能已经过时。
windows下QtCreator的大内存改造(32位)
因为要查看Qt的源代码,因为我用的Qt版本是5.7.0是32位的,所以会出现加载文件过多而崩溃的现象,方法为
1 | editbin /largeaddressaware qtcreator.exe |
修改前先备份原程序,修改好以后通过dumpbin /headers来查看是否多了一条Application can handle large (>2GB) addresses
Unable to set geometry的bug修复
Qt有个bug:当使用QSystemTrayIcon时,可能会用到拦截关闭按钮后隐藏的需求,此时如果最大化后点击关闭按钮那么恢复窗口时则会出现setGeometry: Unable to set geometry的问题.官方的示例也存在该问题.折腾了好久才勉强解决
开始想重载窗口的close()函数,直接调用hide()函数,结果失败,通过阅读帮助发现该函数底层不管如何会首先发送一个QCloseEvent时间(在重载函数调用之前)这就尴尬了.
1 | bool QWidget::close() |
Closes this widget. Returns true if the widget was closed; otherwise returns false.
First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.
经过一阵乱撸找到最终的解决方案如下,在隐藏前需要改变窗口的状态(或者调用showNormal()也可)
1 | //拦截关闭事件 |
程序带上Qt源码调试
打开QtCreator,在工具->选项->调试器->概要 找到添加Qt源码…然后点击找到Qt安装目录下的Src文件夹即可
崩溃收集
如果是Linux环境请下载linux_syscall_support.h放到src/third_party/lss目录下
使用谷歌的breakpad
google的breakpad编写一个.pri文件
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97# ***************************************************************************
# Implemented using http://blog.inventic.eu/2012/08/qt-and-google-breakpad/
# as a the reference.
#
# Get Google Breakpad here: https://code.google.com/p/google-breakpad/
#
# The required breakpad sources have been copied into /src in order to make
# integration with the application smooth and easy.
#
# To use source from Google Breakpad SVN checkout instead, change $$PWD/src
# to path where it was checked out.
#
# ***************************************************************************
# 更新linux下的配置
# convert_UTF.c->convert_UTF.cc
# + breakpad_getcontext.S
# + microdump_writer.cc
# + ucontext_reader.cc
# + thread_info.cc
HEADERS += $$PWD/crashhandler.h
SOURCES += $$PWD/crashhandler.cpp
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/src
# Windows
win32:HEADERS += $$PWD/src/common/windows/string_utils-inl.h
win32:HEADERS += $$PWD/src/common/windows/guid_string.h
win32:HEADERS += $$PWD/src/client/windows/handler/exception_handler.h
win32:HEADERS += $$PWD/src/client/windows/common/ipc_protocol.h
win32:HEADERS += $$PWD/src/google_breakpad/common/minidump_format.h
win32:HEADERS += $$PWD/src/google_breakpad/common/breakpad_types.h
win32:HEADERS += $$PWD/src/client/windows/crash_generation/crash_generation_client.h
win32:HEADERS += $$PWD/src/common/scoped_ptr.h
win32:SOURCES += $$PWD/src/client/windows/handler/exception_handler.cc
win32:SOURCES += $$PWD/src/common/windows/string_utils.cc
win32:SOURCES += $$PWD/src/common/windows/guid_string.cc
win32:SOURCES += $$PWD/src/client/windows/crash_generation/crash_generation_client.cc
# Linux
unix:HEADERS += $$PWD/src/client/linux/minidump_writer/cpu_set.h
unix:HEADERS += $$PWD/src/client/linux/minidump_writer/proc_cpuinfo_reader.h
unix:HEADERS += $$PWD/src/client/linux/handler/exception_handler.h
unix:HEADERS += $$PWD/src/client/linux/crash_generation/crash_generation_client.h
unix:HEADERS += $$PWD/src/client/linux/handler/minidump_descriptor.h
unix:HEADERS += $$PWD/src/client/linux/minidump_writer/minidump_writer.h
unix:HEADERS += $$PWD/src/client/linux/minidump_writer/line_reader.h
unix:HEADERS += $$PWD/src/client/linux/minidump_writer/linux_dumper.h
unix:HEADERS += $$PWD/src/client/linux/minidump_writer/linux_ptrace_dumper.h
unix:HEADERS += $$PWD/src/client/linux/minidump_writer/directory_reader.h
unix:HEADERS += $$PWD/src/client/linux/log/log.h
unix:HEADERS += $$PWD/src/client/minidump_file_writer-inl.h
unix:HEADERS += $$PWD/src/client/minidump_file_writer.h
unix:HEADERS += $$PWD/src/common/linux/linux_libc_support.h
unix:HEADERS += $$PWD/src/common/linux/eintr_wrapper.h
unix:HEADERS += $$PWD/src/common/linux/ignore_ret.h
unix:HEADERS += $$PWD/src/common/linux/file_id.h
unix:HEADERS += $$PWD/src/common/linux/memory_mapped_file.h
unix:HEADERS += $$PWD/src/common/linux/safe_readlink.h
unix:HEADERS += $$PWD/src/common/linux/guid_creator.h
unix:HEADERS += $$PWD/src/common/linux/elfutils.h
unix:HEADERS += $$PWD/src/common/linux/elfutils-inl.h
unix:HEADERS += $$PWD/src/common/linux/elf_gnu_compat.h
unix:HEADERS += $$PWD/src/common/using_std_string.h
unix:HEADERS += $$PWD/src/common/memory.h
unix:HEADERS += $$PWD/src/common/basictypes.h
unix:HEADERS += $$PWD/src/common/memory_range.h
unix:HEADERS += $$PWD/src/common/string_conversion.h
unix:HEADERS += $$PWD/src/common/convert_UTF.h
unix:HEADERS += $$PWD/src/google_breakpad/common/minidump_format.h
unix:HEADERS += $$PWD/src/google_breakpad/common/minidump_size.h
unix:HEADERS += $$PWD/src/google_breakpad/common/breakpad_types.h
unix:HEADERS += $$PWD/src/common/scoped_ptr.h
unix:HEADERS += $$PWD/src/third_party/lss/linux_syscall_support.h
unix:SOURCES += $$PWD/src/client/linux/crash_generation/crash_generation_client.cc
unix:SOURCES += $$PWD/src/client/linux/handler/exception_handler.cc
unix:SOURCES += $$PWD/src/client/linux/handler/minidump_descriptor.cc
unix:SOURCES += $$PWD/src/client/linux/minidump_writer/minidump_writer.cc
unix:SOURCES += $$PWD/src/client/linux/minidump_writer/linux_dumper.cc
unix:SOURCES += $$PWD/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
unix:SOURCES += $$PWD/src/client/linux/log/log.cc
unix:SOURCES += $$PWD/src/client/minidump_file_writer.cc
unix:SOURCES += $$PWD/src/common/linux/linux_libc_support.cc
unix:SOURCES += $$PWD/src/common/linux/file_id.cc
unix:SOURCES += $$PWD/src/common/linux/memory_mapped_file.cc
unix:SOURCES += $$PWD/src/common/linux/safe_readlink.cc
unix:SOURCES += $$PWD/src/common/linux/guid_creator.cc
unix:SOURCES += $$PWD/src/common/linux/elfutils.cc
unix:SOURCES += $$PWD/src/common/string_conversion.cc
unix:SOURCES += $$PWD/src/common/convert_UTF.cc
unix:SOURCES += $$PWD/src/common/linux/breakpad_getcontext.S
unix:SOURCES += $$PWD/src/client/linux/microdump_writer/microdump_writer.cc
unix:SOURCES += $$PWD/src/client/linux/dump_writer_common/ucontext_reader.cc
unix:SOURCES += $$PWD/src/client/linux/dump_writer_common/thread_info.cc
#breakpad app need debug info inside binaries
unix:QMAKE_CXXFLAGS+=-g添加头文件crashhandler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace Breakpad {
class CrashHandlerPrivate;
class CrashHandler
{
public:
static CrashHandler* instance();
void Init(const QString& reportPath);
void setReportCrashesToSystem(bool report);
bool writeMinidump();
private:
CrashHandler();
~CrashHandler();
Q_DISABLE_COPY(CrashHandler)
CrashHandlerPrivate* d;
};
}编写cpp文件crashhandler.cpp
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
namespace Breakpad {
/************************************************************************/
/* CrashHandlerPrivate */
/************************************************************************/
class CrashHandlerPrivate
{
public:
CrashHandlerPrivate()
{
pHandler = NULL;
}
~CrashHandlerPrivate()
{
delete pHandler;
}
void InitCrashHandler(const QString& dumpPath);
static google_breakpad::ExceptionHandler* pHandler;
static bool bReportCrashesToSystem;
};
google_breakpad::ExceptionHandler* CrashHandlerPrivate::pHandler = NULL;
bool CrashHandlerPrivate::bReportCrashesToSystem = false;
/************************************************************************/
/* DumpCallback */
/************************************************************************/
bool DumpCallback(const wchar_t* _dump_dir,const wchar_t* _minidump_id,void* context,EXCEPTION_POINTERS* exinfo,MDRawAssertionInfo* assertion,bool success)
bool DumpCallback(const google_breakpad::MinidumpDescriptor &md,void *context, bool success)
{
Q_UNUSED(context);
Q_UNUSED(_dump_dir);
Q_UNUSED(_minidump_id);
Q_UNUSED(assertion);
Q_UNUSED(exinfo);
qDebug("BreakpadQt crash");
/*
NO STACK USE, NO HEAP USE THERE !!!
Creating QString's, using qDebug, etc. - everything is crash-unfriendly.
*/
return CrashHandlerPrivate::bReportCrashesToSystem ? success : true;
}
void CrashHandlerPrivate::InitCrashHandler(const QString& dumpPath)
{
if ( pHandler != NULL )
return;
std::wstring pathAsStr = (const wchar_t*)dumpPath.utf16();
pHandler = new google_breakpad::ExceptionHandler(
pathAsStr,
/*FilterCallback*/ 0,
DumpCallback,
/*context*/
0,
true
);
std::string pathAsStr = dumpPath.toStdString();
google_breakpad::MinidumpDescriptor md(pathAsStr);
pHandler = new google_breakpad::ExceptionHandler(
md,
/*FilterCallback*/ 0,
DumpCallback,
/*context*/ 0,
true,
-1
);
}
/************************************************************************/
/* CrashHandler */
/************************************************************************/
CrashHandler* CrashHandler::instance()
{
static CrashHandler globalHandler;
return &globalHandler;
}
CrashHandler::CrashHandler()
{
d = new CrashHandlerPrivate();
}
CrashHandler::~CrashHandler()
{
delete d;
}
void CrashHandler::setReportCrashesToSystem(bool report)
{
d->bReportCrashesToSystem = report;
}
bool CrashHandler::writeMinidump()
{
bool res = d->pHandler->WriteMinidump();
if (res) {
qDebug("BreakpadQt: writeMinidump() success.");
} else {
qWarning("BreakpadQt: writeMinidump() failed.");
}
return res;
}
void CrashHandler::Init( const QString& reportPath )
{
d->InitCrashHandler(reportPath);
}
}
- 测试程序
新建一个工程在将breakpad拷贝到3rdparty目录下,然后pro文件中添加1
include($$PWD/3rdparty/breakpad/breakpad.pri)
测试程序main.cpp
1 |
|
- 运行minidump_stackwalk.exe程序分析dmp文件
1
minidump_stackwalk.exe xxxx.dmp symbols > foo.txt 2>&1
7.打开 foo.txt文件
记住该文件下跟exe相关的地方,找到如下图中的eip寄存器地址(该寄存器应该为堆栈地址指针)
- 重新编译文件
在.pro工程中添加以下内容后重新编译
1 | QMAKE_CXXFLAGS_RELEASE += -g |
- 运行addr2line(该软件为Qt自带xxx\Tools\mingw530_32\bin\addr2line.exe)找到源文件中的地址
1
addr2line.exe -e untitled.exe -a 40eaf4 404774
10.效果如下
你就说巧不巧吧……
如果不加调试信息则找不到,但是还可以使用调试工具打开
找到第一个地址4b59然后在调试工具中找到地址发现为窗口显示的下一条语句,嗯听天由命吧
增加一条指令,将文件转为汇编…
1 | objdump -S untilted.exe > test.asm |
静态Qt编译Mysql驱动
- 按照其他教程,下载相应版本的Qt源码放到对应的路径下
- 建立qt_plugin_qsqlmysql.pri
模仿sqlite在路径 …Qt\Qt5.7.1\5.7\mingw53_32_release_static\mkspecs\modules 下建立一个文件内容如下
1 | QT_PLUGIN.qsqlmysql.TYPE = sqldrivers |
这样Qt编译的时候会扫描该目录下的文件,自动导入
- 编译完成后生成的文件为
- libqsqlmysql.a
- qsqlmysql.prl
1
2
3
4
5QMAKE_PRL_BUILD_DIR = C:/Qt/Qt5.7.1/5.7/Src/qtbase/src/plugins/sqldrivers/mysql
QMAKE_PRO_INPUT = mysql.pro
QMAKE_PRL_TARGET = libqsqlmysql.a
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin incremental_off windows qt_build_extra file_copies qt warn_on release link_prl debug_and_release precompile_header release static static_runtime rtti no_plugin_manifest directwrite qpa win32 mingw gcc copy_dir_files precompile_header pcre release sse2 sse3 ssse3 sse4_1 sse4_2 avx avx2 largefile prefix_build force_independent create_prl link_prl prepare_docs qt_docs_targets no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions warning_clean release ReleaseBuild Release build_pass c++11 plugin relative_qt_rpath create_cmake c++11 strict_c++ c++14 c++1z release ReleaseBuild Release build_pass have_target staticlib exclusive_builds no_autoqmake thread moc resources
QMAKE_PRL_LIBS = -llibmysql -LC:/Qt/Qt5.7.1/5.7/mingw53_32_release_static/lib C:/Qt/Qt5.7.1/5.7/mingw53_32_release_static/lib\\libQt5Sql.a -LC:/Qt/Qt5.7.1/5.7/OpenSSL_MinGW32_Static/lib C:/Qt/Qt5.7.1/5.7/mingw53_32_release_static/lib\\libQt5Core.a -lole32 -luuid -lws2_32 -ladvapi32 -lshell32 -luser32 -lkernel32 -lmpr C:/Qt/Qt5.7.1/5.7/mingw53_32_release_static/lib\\libqtpcre.a
编译完成后就行了,但此时还需要拷贝动态链接库libmysql.dll到可执行目录留下,不然运行的时候会报错,一直想解决这个问题(不能完全做到打包到一个文件中)
下载mingw转化工具(reimp.exe)重新编译也许可以(暂时未做尝试) dlltool.exe在Qt的工具目录下就有
1
2reimp -d libmysql.lib
dlltool -k -d libmysql.def -l libmysql.a有需要的自取(转化的版本我试了下5.7的不行,低版本的可以,未继续深入,同时把第二步中的qt_plugin_qsqlmysql.pri改名后既可以不加载mysql了
附件下载
reimp下载
[]
参考文档
您的支持是我前行的动力!