我对以下问题感到困惑:如何保持“静态”标签的优势,但仍能在网站上调试生产代码?
一旦发生意外行为发生在客户站点,并且仅在那里发生。在许多情况下,可以选择执行调试可以节省大量精力并提供非常快速的响应。这样的调试通常涉及检查函数行为,这使我们进入“静态”定义。
无法从调试shell调试静态函数,例如放置断点或执行它。 另一方面,将所有函数定义为公共函数会导致代码结构和优化悲伤。
我知道编辑至少两个不同构建的选项,一个使用静态,一个不使用,但这非常适合自动化测试,而不适用于最终生成的最终生产版本。
将会从您这里获得一些见解,主要是关于您如何解决(如果有的话)这种困境。或者将问题改为:“什么更重要?”
关于C here中“静态”的讨论。
答案 0 :(得分:3)
我认为根本问题不是“你是否附带'静态'?”,它是“你是否准确测试了你的货物?”对于嵌入式代码,如果您在Debug构建上进行大部分测试,然后发送使用不同选项编译的Release版本,那么您实际上是将未经测试的代码发送给您的客户。当您在靠近硬件的情况下运行时,时序或内存访问模式的微小变化(优化器可以轻松引入)可能会导致系统行为发生重大变化。
我目前的策略是发布Debug版本,配置为我在调试时可以进行的尽可能多的优化。没有静态函数,使调试器尽可能多地显示状态。
是的,我放弃了一些可能的编译器生成的效率,但只要我确保Debug版本足够快以满足其要求,那就不是问题了。而且收益是我发布的代码与我在整个发布周期中测试的代码完全相同 - 没有优化器产生的意外。
答案 1 :(得分:1)
某些调试器可以调试“静态”函数。有时静态函数会在调用站点上扩展,这会使调试器的工作变得困难,而且有些调试器只是放弃了。
(呼叫站点的内联扩展实际上并不是特定于“静态”的属性,只是编译器更有可能这样做,因为他们“更了解”该功能 - 特别是,该名称在外部不可见当前的翻译单元,如果所有的调用都是在线扩展的,那么函数的代码就可以完全省略。)
曾经常常使用宏:
#ifndef STATIC
# define STATIC static
#endif
...
STATIC void somefunc() { ... }
然后将宏转换为“无”用于调试版本。这非常有效,但是找到一个足够智能的调试器来处理静态函数甚至更好,即使它们是内联扩展的。
答案 2 :(得分:1)
您可以在可以公开访问的函数中放置一个断点来调用静态函数吗?然后你可以检查进入的参数和返回值至少。如果问题只发生在客户站点,并且您的单元测试/集成测试没有显示您期望这些函数接收的输入问题,则问题可能是这些函数正在获取输入(或输入序列,如果函数是某种状态的有状态)你没有预料到,这意味着实际问题可能超出你正在看的静态函数。
如果您已经怀疑您知道哪个静态函数包含问题,并且您知道您怀疑导致问题的输入类型,那么您可以在发布版本中放置一个简单的单元测试函数来检查您怀疑的错误。当然,如果这个功能直接控制,例如六吨起重机,这会变得复杂,在这种情况下,您可能必须编写两个版本的功能,一个带有用于控制起重机的模型,并对其进行测试。 / p>
最不可能但并非不可能,永远不会排除发布和调试版本之间的编译器不一致。我们都喜欢认为编译器是绝对可靠的,包括我,但事情发生了。我在你对torek的回应中看到,为客户提供调试版本有时会解决问题......