自动编写 MCVE(重现错误的最小源代码)

Writing an MCVE (minimal source code that reproduces an error) automatically?

本文关键字:错误 源代码 MCVE      更新时间:2023-10-16

当我想问一个问题时,例如stackoverflow,我通常必须发布源代码。

问题是,我正在使用相当大的自定义框架,类结构等,并且与问题相关的部分可能在许多地方本地化(有时很难检测到代码的哪些部分对问题很重要)。我无法发布完整的源代码(它太大而无法有效阅读)。

出于这个原因,我通常会努力编写一个最小的代码(通常在一个main.cpp而不是大量的类中)来重现问题。

我想知道 - 是否有可能自动化该过程?这里要做的典型事情是用它们的主体替换方法/函数的调用,将文件合并到一个.cpp,删除所有"未调用"的方法和类,未使用的变量等。

这里真正的困难是区分"它没有做我想做的事","错误消失了,因为我删除了基本代码"和"它现在崩溃了,因为我删除了一些重要的东西"。实际上,在标记某些代码"不需要它"后按删除键是容易的部分。

找出显示问题的关键是困难的部分,并且很难自动化 - 因为有必要了解代码应该做什么和它实际做什么之间的区别。只是随机删除代码是行不通的,因为"新"代码可能会被破坏,因为你删除了一些重要的步骤,而不是因为你删除了未使用的crud - 只有[理解问题]的人才能做到这一点。

考虑一下:

Object* something;
void Initialize()
{
    something = new Object(1, 2, 3);
}
int main()
{
   Initialize();
   // Some more code, some of which SOMETIMES sets something = NULL.
   something->doStuff();  // Will crash if object is NULL.
}

如果我们删除Initialize ,代码每次都会失败,而不仅仅是每第三次失败一次。但这是因为 Object 尚未初始化,而不是代码中的错误 [可能是我们应该在 something->doStuff() 之前添加 if (something) ,或者因为我们不应该将其设置为在"更多代码"中NULL,所以"不要那样做"]。

当我处理一个棘手的问题时,特别是在我们有测试系统自动生成代码以在不同条件下测试不同功能的工作中,我的第一步是使[或采用一些现有的]代码成为"小型独立测试",它小而简单,只做"必要的事情",而不是试图减少数千行复杂代码,做很多额外的事情。

对于某些项目,有一些工具可以帮助识别"哪位代码是问题",例如[bugpoint][1],它可以发现LLVM中的哪个"传递"会导致崩溃。

如果你有一个支持这一点的版本控制系统,你可以"平分"代码,以提出引入特定错误的版本[至少有时]。但是,我在工作中有一个案例,我的一些代码"显然破坏了东西",但事实证明,其他一些代码"自很久以前以来一直被破坏",因为其他代码没有清除 API 手册所说的指针字段应该设置为 NULL ,我的代码正在检查指针以确定它是否指向正确的类型的东西 - 它当值是"无论碰巧在堆栈的那部分"时,这是非常错误的,所以它不是NULL的,也不是一个有效的指针。我只是添加了使此错误明显的代码,而不是隐藏自己。

[1] http://llvm.org/docs/CommandGuide/bugpoint.html