我们正在制作一个可移植的代码(win+macOs),并且我们正在研究如何使代码更加健壮,因为它经常崩溃......(通常是溢出或错误的初始化):-(
我读到谷歌浏览器对每个标签都使用一个进程,所以如果出现问题,程序不会完全崩溃,只有那个标签。我认为这很整洁,所以我可以试一试!
所以我想知道是否有人有一些提示、帮助、阅读列表、评论或可以帮助我构建更多 rubust c++ 代码的东西(便携总是更好)。
在同一主题中,我还想知道是否有一个可移植的进程库(如 boost)?
非常感谢。
我们正在制作一个可移植的代码(win+macOs),并且我们正在研究如何使代码更加健壮,因为它经常崩溃......(通常是溢出或错误的初始化):-(
我读到谷歌浏览器对每个标签都使用一个进程,所以如果出现问题,程序不会完全崩溃,只有那个标签。我认为这很整洁,所以我可以试一试!
所以我想知道是否有人有一些提示、帮助、阅读列表、评论或可以帮助我构建更多 rubust c++ 代码的东西(便携总是更好)。
在同一主题中,我还想知道是否有一个可移植的进程库(如 boost)?
非常感谢。
Chrome 的答案更多的是关于故障缓解,而不是代码质量。做 Chrome 正在做的事情就是认输。
坦率地说,如果您的软件经常由于溢出和错误的初始化而崩溃,那么您将遇到一个非常基本的编程质量问题,并且不容易解决。这听起来很杂乱无章,这不是我的意图。我的观点是,错误代码的问题必须是您最关心的问题(我敢肯定)。诸如 Chrome 或自由使用异常处理来捕获程序缺陷之类的东西只会分散您对真正问题的注意力。
我开发了许多多平台 C++ 应用程序(最大的是 150 万行代码并在 7 个平台上运行——AIX、HP-UX PA-RISC、HP-UX Itanium、Solaris、Linux、Windows、OS X) . 实际上,您的帖子中有两个完全不同的问题。
不稳定。你的代码不稳定。修理它。
跨平台编码。
就个人而言,我会先稳定代码(不添加任何更多功能),然后处理跨平台问题,但这取决于你。请注意,Visual Studio 有一个出色的调试器(正是因为这个原因,上面提到的代码库才被移植到 Windows)。
你没有提到目标项目是什么;每个选项卡都有一个进程并不一定意味着更“健壮”的代码。无论可移植性如何,您都应该致力于编写带有测试的可靠代码 - 只需阅读有关编写良好 C++ 代码的信息 :)
至于可移植性部分,请确保您从第一天起就在两个平台上进行测试,并确保在解决特定于平台的问题之前不编写新代码。
你真的,真的不想做 Chrome 正在做的事情,它需要一个进程管理器,这可能对你想要的东西来说太过分了。
您应该研究使用来自 Boost 的智能指针或其他将为 C++ 提供引用计数或垃圾收集的工具。
或者,如果您经常崩溃,您可能需要考虑使用具有 C++ 绑定的脚本语言编写应用程序的非性能关键部分。
Scott Meyers 的Effective C++和More Effective C++非常好,而且读起来很有趣。
Steve McConnell 的Code Complete是许多人的最爱,包括 Jeff Atwood。
Boost 库可能是一个很好的选择。我工作的一个项目使用它们。我自己只使用过WIN32线程。
我同意托拉克的观点。
糟糕的初始化或溢出是代码质量差的迹象。
谷歌这样做是因为有时无法控制页面中执行的代码(由于插件错误等)。因此,如果您使用的是低质量插件(它确实发生了),也许 Google 解决方案对您有好处。
但是一个经常崩溃的没有插件的程序只是写得不好,或者非常非常复杂,或者非常老旧(并且缺少很多维护时间)。您必须停止开发,并调查每一次崩溃。在 Windows 上,使用 PDB(程序数据库)编译模块,每次崩溃时,附加一个调试器。
您还必须添加内部测试。避免模式:
doSomethingBad(T * t)
{
if(t == NULL) return ;
// do the processing.
}
这是一个非常糟糕的设计,因为错误就在那里,而这次你只是避免它。但是没有这个守卫的下一个函数会崩溃。最好尽快崩溃以离错误更近。
相反,在 Windows 上(MacOS 上必须有类似的 API)
doSomethingBad(T * t)
{
if(t == NULL) ::DebugBreak() ; // it will call the debugger
// do the processing.
}
(不要直接使用这段代码...把它放在一个define中以避免将其传递给客户端...)您可以选择适合您的错误API(异常,DebugBreak,assert等),但使用它在代码知道有问题的那一刻停止。
尽可能避免使用 C API。使用 C++ 习语(RAII 等)和库。
ETC..
PS:如果您使用异常(这是一个不错的选择),请不要将它们隐藏在 catch 中。你只会让你的问题变得更糟,因为错误就在那里,但程序会尝试继续,并且有时可能会在之后崩溃,同时破坏它所触及的任何东西。
你总是可以在你的程序中添加异常处理来捕捉这些类型的错误并忽略它们(尽管细节是特定于平台的)......但这非常是一把两刃剑。而是考虑让程序捕获异常并创建转储文件以进行分析。
如果您的程序以意想不到的方式运行,您对内部状态了解多少?也许崩溃的例程/线程损坏了一些关键数据结构?也许如果您发现错误并尝试继续,用户将保存他们正在处理的任何内容并将损坏提交到磁盘?
除了编写更稳定的代码之外,这里有一个可以回答您问题的想法。
无论您使用的是进程还是线程。您可以编写一个小/简单的看门狗程序。然后您的其他程序向该看门狗注册。如果任何进程死亡,或线程死亡,它可以由看门狗重新启动。当然,您需要进行一些测试以确保您不会继续重新启动相同的错误线程。即:重新启动它 5 次,然后在第 5 次之后,关闭整个程序并记录到文件/syslog。
使用调试符号构建您的应用程序,然后添加异常处理程序或配置 Dr Watson 以生成故障转储(运行 drwtsn32.exe /i 将其安装为调试器,无需 /i 即可弹出配置对话框)。当您的应用程序崩溃时,您可以通过查看调用堆栈和变量来检查它在 windbg 或 Visual Studio 中的问题所在。
谷歌符号服务器了解更多信息。
显然,您可以使用异常处理使其更健壮并使用智能指针,但最好修复错误。
构建它的想法是退出的唯一方法是让程序崩溃并且它可以随时崩溃。当你以这种方式构建它时,崩溃永远不会/几乎永远不会丢失任何数据。一两年前我读过一篇关于它的文章。可悲的是,我没有指向它的链接。
将其与某种故障转储相结合,并通过电子邮件发送给您,以便您解决问题。
我建议您编译一个 linux 版本并在Valgrind下运行它。
Valgrind 将跟踪内存泄漏、未初始化的内存读取和许多其他代码问题。我强烈推荐它。
经过超过 15 年的 Windows 开发,我最近编写了我的第一个跨平台 C++ 应用程序 (Windows/Linux)。就是这样:
我使用 NetBeans C++ 构建 Linux 并立即拥有完整的 Linux 端口。