假设有一个名为LongFunction的1000行代码的函数,我们使用它:
bool bSuccess = LongFunction(); assert(bSuccess);
这里我在调试时得到一个断言,我知道LongFunction有问题,所以我需要找到函数遇到问题的地方并返回:
它有效,但有以下问题:
您对如何查明问题还有其他创意吗?
编辑:以下是一些让我们关注问题的细节。
编辑 :当前讨论的摘要:
我们有一些争议:
我们有2个合理的解决方案:
显然你应该重构这个函数,但在C ++中你可以使用这个简单的权宜之计在五分钟内解决这个问题:
class ReturnMarker { public: ReturnMarker() {}; ~ReturnMarker() { dummy += 1; //<-- put your breakpoint here } static int dummy; } int ReturnMarker::dummy = 0;
然后在函数顶部实例化一个ReturnMarker。 当它返回时,该实例将超出范围,您将点击析构函数。
void LongFunction() { ReturnMarker foo; // ... }
听起来好像是重构LongFunction()的时候了……
一个1000行function是一个坏代码气味。 花时间将其重构为更小,更易维护的function。 您可以在遇到错误时找到错误,这对未来将是一次值得的投资。
这是C还是C ++?
如果是C ++,创建一个包含bool(比如CMyBool)的新类,它会自动转换为bool。
现在让LongFunction返回CMyBool(快速搜索和替换会将LongFuntion中的所有返回值更改为“返回CMyBool(x)”。
现在在CMyBool的ctor中设置一个断点,调试器现在将在创建CMyBool时停止,这将在LongFunction中的正确返回语句上。
自动强制转换为bool将阻止CMyBool破坏使用CMyBool的代码。
这将使您了解最初的问题,但更大的问题是LongFunction需要重构。
希望这可以帮助。
如果你的问题只是普通的懒惰(没有错误),请确保LongFunction中的所有return语句都是
return(value);
而不是
return value;
(例如使用正则表达式搜索和替换)
然后,使用一个slighlty修改的预处理器宏比原始建议:
#define return(value) { if (!value) TRACE(__LINE__); return(value); }
…甚至
#define return(value) { assert(value); return(value); }
……或者你认为合适的任何东西
你还没有说过你的平台。 根据LongFunction
的内容,以下是我如何使用gdb来解决这个问题:
让我们假设你的文件’f.cc’有以下几行:
1: bool LongFunction () { /* ... */ } 2: 3: void bar () 4: { 5: bool bSuccess = LongFunction (); 6: assert (bSuccess); 7: }
以下是gdb中的步骤:
我之所以说它取决于LongFunction的内容,是因为如果LongFunction从流中读取输入,或修改全局变量等,那么第二轮的行为可能会有所不同。 您应该将上述步骤视为代码如下:
3: void bar () 4: { 5: bool bSuccess = LongFunction (); 5: bSuccess = LongFunction (); 6: assert (bSuccess); 7: }
它是visual studio我会在断言上放置一个断点,然后使用堆栈跟踪窗口单击下一行,然后将进入该方法的退出点。
#define return { TRACE(LINE); return; }
这解决了你的问题4。
就其他问题而言,这就是编码的问题。 这就是为什么许多系统在出现问题时将更复杂的错误(例如来自COM对象的HRESULT)和/或垃圾邮件返回到调试流的原因。
但是应该重新考虑1000行函数。 正如您所看到的那样,长期function难以维护。
编辑:以下工作会比上面的更好吗?
#define return TRACE(LINE), return
喝了几杯,所以可能没有。
“我可能会逐步调试它,它可以工作,但很耗时,我们不会这样做。”
你怎么调试?
我曾经调试过:
1)找到一组重现问题的参数。
2)使用该组参数逐步执行代码。
如果有1000行代码,那么如果不完全知道函数的function和应该做什么,你将如何“重构”。
如果不单独执行该function,您将如何做到这一点。 我认为这是一个带有良好调试器的IDE。
坦率地说,我发现这个问题几乎是一种非常悲伤的问题。
1982年,我的任务是修复一个破碎的流程图程序。 该程序是用机器相关的Harris FORTRAN编写的(我现在不记得它是在FORTRAN IV还是FORTRAN 77中),由一个1100行的主程序,一个900行子程序和大约十几个子程序组成。长10到20行。
哦,程序中几乎没有空格(空白行),评论根本没用。
我花了160个小时 – 四个星期,全部时间,我的桌子上没有其他东西 – 弄清楚那些代码足以进行适当的修理。
你处于类似的情况。 这将花费你真正的CPU时间投资,让你找到1000行的生物,足以解决所有可能出错的问题,以及如何解决它。
找到回报很容易。 对于Microsoft AbysmalC ++:搜索“return”的每个实例并在其前面加上
“printf(” n n — >>>在%d n n“,__LINE__行冲出);”
(或您系统上的等效物)。 显然,你不能自动这样做; 你必须看看当地的包围。 然后运行测试,看看它告诉你的样子。
事实是:在现实的计算世界里,几乎没有真正的例程,实际上需要1000行长。 在近40年的时间里,作为学生和专业人士,我只遇到了一个需要长于一个打印机页面(大约60行)的例行程序,而且这个例子非常特殊。 全部讲述了大约三页。
另一方面,我已经看到很多运行模块,编写它的人太懒,或者太无能,无法正确地考虑因素,维护程序员太懒,太无能,或者太害怕他们的经理回去重构它。
最后:考虑到这可能不是最后一次有人必须处理这个模块,而且可能不是你最后一次必须处理它。 这些东西往往是焦油宝宝:一旦你触摸它们,你永远不会脱离它们。 至少可能值得花时间进行重构,并且很可能从SCRATCH和第一原则重新设计/重写它。
以上就是c/c++开发分享如何确定long函数返回的位置相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/545846.html