如何确定长函数返回的位置

时间:2009-08-21 10:28:48

标签: c++ c return

假设有一个名为LongFunction的1000行代码的函数,我们使用它:

bool bSuccess = LongFunction();
assert(bSuccess);

这里我在调试时得到了一个断言,我知道LongFunction有问题,所以我需要找到函数遇到问题的地方并返回:

  1. 我可能会一步一步地调试它,它可以工作但很耗时,我们不会这样做。

  2. 我可以搜索关键字“返回”(或者更精确的搜索使用RegExp),并在那些返回时设置断点,它应该更快,但它仍然是乏味的手动工作,无法自动化。

  3. #define返回TRACE( LINE );返回

  4. 它有效但有以下问题:

    • 它会打印太多冗余信息,因为经常使用返回。(或者我们可以使用一些EnvVar来打开或关闭它)
    • 不适用于以下情况:if(bOK)返回true;

    您对如何查明问题有任何其他创意吗?

    修改 以下是一些让我们关注问题的细节。

    1. 这是关于C ++,而不是平台规范。

    2. 我们不想重构函数(是的,我知道我们应该),我们甚至不想更改任何代码 - 此时我们只想提供一些工具来进行应用程序调试更轻松。我也相信这应该是一个共同的要求,难道你不碰到这个吗?

    3. LongFunction()有多个退出点,返回类型不是必须bool(HRESULT,用户定义的错误代码......)

    4. 修改:当前讨论的摘要:
      我们有一些争议:

      1. 你应该重构这个功能 是的,每个人都知道我们应该,但这不是重点。如果我打电话重构函数,我不会在这里问这个问题。

      2. 查找LongFunction()返回失败的位置无效。
        我总是首先找到错误发生的地方,知道发生了什么,我很好奇为什么这没有用,你在这种情况下做了什么? (假设我已经熟悉该功能的工作原理)

      3. 我们有两个合理的解决方案:

        1. 来自Crashworks的ReturnMarker,函数中的堆栈对象将在函数返回时进行破坏,在析构函数中设置断点将显示它在debuger中返回的位置

        2. 来自Binary&的CMyBool(x) Sadsido,将LongFunction的返回类型更改为可以从bool构造的CMyBool,从LongFunction返回将构造该对象,因此只需在构造函数中设置断点即可。

9 个答案:

答案 0 :(得分:13)

显然你应该重构这个函数,但是在C ++中你可以使用这个简单的权宜之计在五分钟内解决这个问题:

class ReturnMarker
{
   public:
   ReturnMarker()  {};
   ~ReturnMarker() 
   {
      dummy += 1; //<-- put your breakpoint here
   }
   static int dummy;
}

int ReturnMarker::dummy = 0;

然后在函数顶部实例化一个ReturnMarker。当它返回时,该实例将超出范围,你将点击析构函数。

void LongFunction()
{
    ReturnMarker foo;

    // ...
}

答案 1 :(得分:8)

听起来好像重构LongFunction()......

1000行功能是一种糟糕的代码味道。花时间将其重构为更小,更易维护的功能。你会发现这些错误,这对未来来说是一项值得的投资。

答案 2 :(得分:4)

这是C还是C ++?

如果是C ++,请创建一个包含bool(比如CMyBool)的新类,它会自动转换为bool。

现在让LongFunction返回CMyBool(快速搜索和替换会将LongFuntion中的所有返回值更改为“返回CMyBool(x)”。

现在在CMyBool的ctor中设置一个断点,调试器现在将在创建CMyBool时停止,这将在LongFunction中的正确return语句上。

自动强制转换为bool将阻止CMyBool破坏使用CMyBool的代码。

这会让你解决最初的问题,但更大的问题是LongFunction需要重构。

希望这有帮助。

答案 3 :(得分:4)

如果你的问题只是普通的懒惰(没有错误),请确保LongFunction中的所有return语句都是

形式
return(value);

而不是

return value;

(例如使用正则表达式搜索和替换)

然后,使用比原始建议更简洁的修改后的预处理器宏:

#define return(value) { if (!value) TRACE(__LINE__); return(value); }

......甚至

#define return(value) { assert(value); return(value); }

......或者你认为合适的任何东西

答案 4 :(得分:0)

#define return { TRACE(LINE); return; }

这解决了你的问题4.

就其他问题而言,这就是编码的问题。这就是为什么许多系统在出现问题时将更复杂的错误(例如来自COM对象的HRESULT)和/或垃圾邮件返回到调试流的原因。

虽然应该重新制作1000行功能。正如您所看到的那样,长期功能难以维护。

编辑:以下工作会比上面更好吗?

#define return TRACE(LINE), return

喝了几杯,所以可能没有。

答案 5 :(得分:0)

你还没有说过你的平台。根据{{​​1}}的内容,以下是我使用gdb:

的方法

让我们假设你的文件'f.cc'有以下几行:

LongFunction

以下是gdb中的步骤:

  1. 在断言的同一行添加断点:1: bool LongFunction () { /* ... */ } 2: 3: void bar () 4: { 5: bool bSuccess = LongFunction (); 6: assert (bSuccess); 7: }

  2. 在bSuccess为false时为该断点添加条件:break f.cc:6

  3. 运行程序直到达到该断点

  4. 在函数体的开头设置断点:condition 1 (bSuccess==0)

  5. 跳回该位置(它将在断点处停止):break f.cc:4

  6. 调试LongFunction的内容以查看它失败的原因。

  7. 我说它取决于LongFunction的内容的原因是,如果LongFunction从流中读取输入,或者修改全局变量等,那么第二轮的行为可能会有所不同。您应该将上述步骤视为代码如下:

    jump f.cc:4

答案 6 :(得分:0)

它是visual studio我会在断言上放置一个断点,然后使用堆栈跟踪窗口单击下一行,然后将进入该方法的出口点。

答案 7 :(得分:0)

“我可能会一步一步地调试它,它可以工作但很耗时,我们不会这样做。”

你怎么调试?

我曾经通过以下方式进行调试:

1)找到一组重现问题的参数。

2)使用那组参数逐步执行代码。

如果有1000行代码,那么在不完全知道函数的作用和应该做什么的情况下,你将如何“重构”。

如果不单独执行该功能,你将如何做到这一点。我认为这是一个带有良好调试器的IDE。

坦率地说,我发现这个问题几乎是一种非常悲伤的问题。

答案 8 :(得分:0)

1982年,我的任务是修复一个破碎的流程图程序。该程序是用依赖于机器的Harris FORTRAN编写的(我现在不记得它是在FORTRAN IV还是FORTRAN 77中),由一个1100行的主程序,一个900行子程序和大约十几个子程序组成。长10至20行。

哦,程序中几乎没有空格(空行),评论根本没用。

花了我160个小时 - 四个星期,全部时间,我的桌子上没有其他东西 - 弄清楚这些代码,以便进行适当的修理。

你处于类似情况。你需要花费一些真正的CPU时间来投资这个1000行的生物,足以解决所有可能出错的问题,以及如何解决这个问题。

找到回报很容易。对于Microsoft AbysmalC ++:搜索“return”的每个实例,并在其前面加上

“printf”(“\ n \ n ---&gt;&gt;&gt;”在第%d行打出\ n \ n \ n \ n \ n \ n \ n“,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _显然,你不能自动这样做;你必须看看当地的包围。然后运行测试,看看它告诉你的位置。

事实就是这样:在现实的计算世界中,几乎没有真正的例程,实际上需要1000行长。在近40年的时间里,作为学生和专业人士,我只遇到了一个需要比一个打印机页面(大约60行)长的例程,而且这个例子非常特殊。全部讲述了大约三页。

另一方面,我已经看到很多运行模块,编写它的人太懒,或者太无能,无法正确地考虑因素,维护程序员太懒,太无能,或者太害怕他们的经理回去重构它。

最后:考虑到这可能不是最后一次有人必须处理这个模块,而且可能不是你最后一次必须处理它。这些东西往往是焦油宝宝:一旦你触摸它们,你永远不会从它们中脱离出来。至少可能值得花时间进行重构,并且很可能从SCRATCH和第一原则重新设计/重写它。