为什么 winmain 参数彼此不匹配?
Why winmain parameters doesn't match to each other?
为什么 QApp 构造函数因 WinMain
个参数而失败?
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPTSTR _lpCmdLine, int _nShowCmd) {
QApplication app(_nShowCmd, & _lpCmdLine);
这里失败并出现异常:
Exception at adress 0x0F3621DC (Qt5Guid.dll) in updater_app.exe: 0xC0000005
怎么了?如何解决?
UPD:
它的工作方式是这样的:
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPTSTR _lpCmdLine, int _nShowCmd) {
int nShowCmd(0);
QApplication app(nShowCmd, & _lpCmdLine);
_lpCmdLine
是 10 而 _nShowCmd
是空字符串 - 所以它不匹配。为什么?
Qt 应用程序 QApplication
主对象应该在标准主函数中创建:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// more app objects initialization
return app.exec();
}
而你:
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPTSTR _lpCmdLine, int _nShowCmd)
{
QApplication app(nShowCmd, & _lpCmdLine);
return app.exec();
}
这意味着 &_lpCdLine
等同于 argv
但是:
LPTSTR _lpCmdLine
等同于 char*
并且您获取它的地址,因此 &_lpCmdLine
匹配 char**
当 _lpCmdLine
指向连续的字符缓冲区而不是字符串数组 argv
.
考虑 main()
函数是如何在 Windows 上实现的是有意义的。有一个很好的讨论:WINMAIN and main() in C++ (Extended) Mind that the C runtime must be initialized before main()
function runs and that may depend on compiler/linker. And also find an example of Qt application main function.
我想当你通过引入 nShowCmd == 0
让你的代码不崩溃时,QApplication
对象不会读取命令行,这可以防止通过解释为地址的随机内容进行不正确的访问_lpCmdLine
。但这仍然是错误的,并且 QApplication
对象的初始化不完整。
作者没有看到 window 而是看到了控制台,这与不启动任何 window 的主要功能代码不完整有关。此外,QML application main.cpp 可能会有所帮助。
由于这个问题再次与 Qt6 相关,这里有一个非常简单的 VisualStudio 解决方案,使用 WinMain 作为入口点:
QApplication app(__argc, __argv);
__argc 和 __argv 由 Microsoft 编译器填充
(在这里找到这个建议:https://codingmisadventures.wordpress.com/2009/03/10/retrieving-command-line-parameters-from-winmain-in-win32/)
问题的简短说明:将 main() 与 VC 一起使用需要使用 Subsystem:Console,但这总是会打开一个控制台 window,您通常希望避免这种情况。你无法摆脱这个控制台,除非使用一些非常肮脏的技巧。因此,您需要切换到 Subsystem:Windows 才能启动“静默”应用程序,但这需要使用 WinMain() 作为应用程序入口点。在 Qt5 之前,qtmain.lib 中有一个自己的 WinMain() 实现,您只需将其链接进去,然后转发到 main() 函数,但这在 Qt6 中已被踢出。该问题只存在于 MSVC 用户,因为使用 mingw 您可以禁用控制台 window 并继续使用 main(),如 Qt 示例中所示。
为什么 QApp 构造函数因 WinMain
个参数而失败?
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPTSTR _lpCmdLine, int _nShowCmd) {
QApplication app(_nShowCmd, & _lpCmdLine);
这里失败并出现异常:
Exception at adress 0x0F3621DC (Qt5Guid.dll) in updater_app.exe: 0xC0000005
怎么了?如何解决?
UPD:
它的工作方式是这样的:
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPTSTR _lpCmdLine, int _nShowCmd) {
int nShowCmd(0);
QApplication app(nShowCmd, & _lpCmdLine);
_lpCmdLine
是 10 而 _nShowCmd
是空字符串 - 所以它不匹配。为什么?
Qt 应用程序 QApplication
主对象应该在标准主函数中创建:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// more app objects initialization
return app.exec();
}
而你:
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPTSTR _lpCmdLine, int _nShowCmd)
{
QApplication app(nShowCmd, & _lpCmdLine);
return app.exec();
}
这意味着 &_lpCdLine
等同于 argv
但是:
LPTSTR _lpCmdLine
等同于 char*
并且您获取它的地址,因此 &_lpCmdLine
匹配 char**
当 _lpCmdLine
指向连续的字符缓冲区而不是字符串数组 argv
.
考虑 main()
函数是如何在 Windows 上实现的是有意义的。有一个很好的讨论:WINMAIN and main() in C++ (Extended) Mind that the C runtime must be initialized before main()
function runs and that may depend on compiler/linker. And also find an example of Qt application main function.
我想当你通过引入 nShowCmd == 0
让你的代码不崩溃时,QApplication
对象不会读取命令行,这可以防止通过解释为地址的随机内容进行不正确的访问_lpCmdLine
。但这仍然是错误的,并且 QApplication
对象的初始化不完整。
作者没有看到 window 而是看到了控制台,这与不启动任何 window 的主要功能代码不完整有关。此外,QML application main.cpp 可能会有所帮助。
由于这个问题再次与 Qt6 相关,这里有一个非常简单的 VisualStudio 解决方案,使用 WinMain 作为入口点:
QApplication app(__argc, __argv);
__argc 和 __argv 由 Microsoft 编译器填充 (在这里找到这个建议:https://codingmisadventures.wordpress.com/2009/03/10/retrieving-command-line-parameters-from-winmain-in-win32/)
问题的简短说明:将 main() 与 VC 一起使用需要使用 Subsystem:Console,但这总是会打开一个控制台 window,您通常希望避免这种情况。你无法摆脱这个控制台,除非使用一些非常肮脏的技巧。因此,您需要切换到 Subsystem:Windows 才能启动“静默”应用程序,但这需要使用 WinMain() 作为应用程序入口点。在 Qt5 之前,qtmain.lib 中有一个自己的 WinMain() 实现,您只需将其链接进去,然后转发到 main() 函数,但这在 Qt6 中已被踢出。该问题只存在于 MSVC 用户,因为使用 mingw 您可以禁用控制台 window 并继续使用 main(),如 Qt 示例中所示。