Visual Studio 2017 2019 2022 调试过程中F10单步卡顿(解决方法)
{mtitle title="IDE -> 工具 -> 选项"/}
- 调试 -> 将所有输出衡口文本里定向到即时窗口 [启用]
- 调试 -> 在变量窗口中显示对象的原始结构 [启用]
- 如图所示
{mtitle title="IDE -> 工具 -> 选项"/}
微软什么的最讨厌啦~写个 GUI 程序要么带个控制台窗口,要么就得用非主流的 WinMain 函数作入口。
用 gcc 的话,这其实不是个问题,带上一个 -mwindows 参数即可顺利解决掉控制台窗口并且抛弃 WinMain。
而到了 Visual Studio,似乎很两难:
Linker 参数中 SubSystem 选择 Windows 可以去除控制台窗口,但会要求用 WinMain 作入口。
Linker 参数中 SubSystem 选择 Console 可以使用 main 作入口,但会自带控制台窗口。
于是困惑了。好在今天在 Irrlicht 的教程中见到了解法:
Linker 参数中的 SubSystem 继续选择 Windows,与此同时将 Entry Point 设置为 mainCRTStartup 即可兼得鱼和熊掌。
以命令行参数形式就是:/SUBSYSTEM:windows /ENTRY:mainCRTStartup
要点就是 ENTRY 参数有三种:mainCRTStartup、WinMainCRTStartup、和 _DllMainCRTStartup,分别对应调用 main、WinMain、和 DllMain,默认是根据 /DLL 和 /SUBSYSTEM 参数自动选择的。
#ifdef _DEBUG
#ifdef UNICODE
#pragma comment(linker, "/subsystem:\"console\" /entry:\"wWinMainCRTStartup\"")
#else
#pragma comment(linker, "/subsystem:\"console\" /entry:\"WinMainCRTStartup\"")
#endif
#endif
#include <codecvt>
#include <locale>
namespace std
{
class codecvt_chs : public std::codecvt_byname<wchar_t, char, std::mbstate_t>
{
public:
explicit codecvt_chs() : codecvt_byname("chs")
};
}
static bool U2W(const std::string& source, std::wstring& buffer)
{
try
{
buffer.swap(*const_cast<std::wstring*>(std::addressof(static_cast<const std::wstring&>(std::wstring(std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(source))))));
return true;
}
catch (const std::range_error& ex)
{
printf("%s", ex.what());
}
return false;
}
static bool W2U(const std::wstring& source, std::string& buffer)
{
try
{
buffer.swap(*const_cast<std::string*>(std::addressof(static_cast<const std::string&>(std::string(std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(source))))));
return true;
}
catch (const std::range_error& ex)
{
printf("%s", ex.what());
}
return false;
}
static bool A2W(const std::string& source, std::wstring& buffer)
{
try
{
buffer.swap(*const_cast<std::wstring*>(std::addressof(static_cast<const std::wstring&>(std::wstring(std::wstring_convert<std::codecvt_chs>().from_bytes(source))))));
return true;
}
catch (const std::range_error& ex)
{
printf("%s", ex.what());
}
return false;
}
static bool W2A(const std::wstring& source, std::string& buffer)
{
try
{
buffer.swap(*const_cast<std::string*>(std::addressof(static_cast<const std::string&>(std::string(std::wstring_convert<std::codecvt_chs>().to_bytes(source))))));
return true;
}
catch (const std::range_error& ex)
{
printf("%s", ex.what());
}
return false;
}
static bool U2A(const std::string& source, std::string& buffer)
{
std::wstring temp;
{
if (U2W(source, temp) && W2A(temp, buffer))
{
return true;
}
}
return false;
}
static bool A2U(const std::string& source, std::string& buffer)
{
std::wstring temp;
{
if (A2W(source, temp) && W2U(temp, buffer))
{
return true;
}
}
return false;
}
1.使用 cmake 生成 mysql 项目.
2.删除无关项目,仅留下以下列表项目文件(这11个项目文件编译出来的就是mysqlclient)
3.自行玻璃原有的第三方依赖库
4.添加项目并引用
5.8.0类似方法,自行去精简你的MySQL源代码吧。
说说抽取项目文件优点:
1.支持源码级调试,f12 未调试时可随时跟踪源代码。
2.减少项目依赖,让所有被依赖项成立树关系,减少工程配置项,使用项目引用。
3.你想到的我想不到,反正在windows下这种引用MySQLClient的方式,笔者认为更好。
4.减少MySQL自身大小,让这种关系在整个项目中被编译器优化。
- 1. libmysql\vsprojects\libmysql\authentication_win\auth_win_client.vcxproj
- 2. libmysql\vsprojects\libmysql\clientlib.vcxproj
- 3. libmysql\vsprojects\extra\comp_err.vcxproj
- 4. libmysql\vsprojects\dbug\dbug.vcxproj
- 5. libmysql\vsprojects\libmysql\libmysql.vcxproj
- 6. libmysql\vsprojects\mysys\mysys.vcxproj
- 7. libmysql\vsprojects\mysys_ssl\mysys_ssl.vcxproj -- 依赖 OpenSSL
- 8. libmysql\vsprojects\strings\strings.vcxproj
- 9. libmysql\vsprojects\vio\vio.vcxproj
- 10. libmysql\vsprojects\zlib\zlib.vcxproj -- 可替换
- 11. libmysql\vsprojects\extra\zlib_decompress.vcxproj -- 可删除
关系顺序
MySQL -> OpenSSL -> Zlib
Curl -> OpenSSl -> Zlib
我的项目 -> OpenSSL -> Zlib
最终成为: 我的项目 -> MySQL -> CURL -> OpenSSL -> Zlib