为啥VC++ 2010编译器在编译简单代码时会崩溃?

Posted

技术标签:

【中文标题】为啥VC++ 2010编译器在编译简单代码时会崩溃?【英文标题】:Why does VC++ 2010 compiler crash when compiling simple code?为什么VC++ 2010编译器在编译简单代码时会崩溃? 【发布时间】:2011-05-16 11:26:38 【问题描述】:

我遇到了一个很奇怪的症状。谁能告诉我根本原因是什么?

我的 VC++ 编译器版本是最新的:“Microsoft Visual C++ 2010 : 01019-532-2002102-70860”

重现步骤:

    创建一个空的 win32 控制台项目 添加一个名为 main.cpp 的新 cpp 文件 将以下代码粘贴到 main.cpp 中 编译 编译器崩溃并报告以下消息:

\bug\main.cpp(54893757):致命错误 C1001:发生内部错误 在编译器中。 (编译文件 'msc1.cpp',第 1420 行)

要解决此问题,请尝试 简化或改变程序 在上面列出的位置附近。 请选择技术支持 Visual C++ 帮助菜单上的命令, 或打开技术支持帮助 文件以获取更多信息。

注入文本中出现此错误:

d:\bug\main.cpp(63) :参见参考 函数模板实例化 'XDummy Test(T)' 正在编译 [ T=int]

构建失败。

下面是main.cpp的源码:

#include <vector> 

template<class It_> 
struct trait_dummy 
 
    static const int value = std::tr1::is_convertible<typename iterator_traits<It_>::iterator_category, int>::value;     
; 

template<class It_> 
class X 
 
public: 
    template<class T_> 
    X(T_& rColl) 
     
; 

template<class T_> 
X<typename T_::iterator> f(T_ rColl, std::false_type) 
 
    return X<typename T_::iterator>(rColl); 
 

template<class T_> 
auto f(T_& rColl) -> decltype(f(rColl, std::false_type())) 
 
    return f(rColl, std::false_type()); 
 

template<class It_> 
X<It_> f(It_ first, size_t nSize, typename std::tr1::enable_if<trait_dummy<It_>::value>::type* dummy = 0) 
 
    return X<It_>(first, first + nSize); 
 

class XTest 
 
public: 
    void foo() 
     
        auto v = f(m_Suite); 
        

    std::vector<int> m_Suite; 
; 

const int g_dummy = 0; 
class XDummy 
 
public: 
    XDummy(int, int, int, int dummy = g_dummy) 
     
; 

template<class T> 
XDummy Test(T) 
    
    return XDummy(0, 0, 0); 
 

int main() 
 
    Test(0); 
    //XTest().foo(); 

    return 0; 

【问题讨论】:

如果您可以将代码减少到导致内部编译器错误的最少代码,请考虑在Microsoft Connect 提交错误报告。 使用这样的 auto 关键字似乎很糟糕/懒惰。我不想挖掘多个函数调用层来找出函数返回的类型。如果内部函数的返回类型发生变化,我宁愿在调用更改的函数时得到编译器错误,而不是向上两层,想知道发生了什么并不得不寻找连锁变化的原因(s )... 在定义局部迭代器变量时使用 auto 很方便,但在函数签名中使用它似乎是个坏主意。 @Leo Davidson:我也不喜欢 auto + decltype。但是,很多情况下,auto + decltype 是必不可少的。如果没有必要,我不会用它们来定义函数。 抱歉,我没有注意到同一行的“->”内容! Auto 在那里可能是完全合理的。 @Tomalak,很高兴 C++ 社区的进步,因为模板被归类为“基本”:) 【参考方案1】:

您自己尝试过任何类型的故障排除吗?

我可以使用您描述的上述源代码重现崩溃。当然,我收到了一些警告:

“IntelliSense:没有重载函数“f”的实例与参数列表匹配” “IntelliSense:函数调用中的参数太少”

都指这一行:

auto v = f(m_Suite); 

再过几秒钟的故障排除发现,通过注释掉整个 XTest 类,代码可以毫无问题地编译和执行(最重要的是,不会导致编译器崩溃)。这告诉我(并且应该告诉您)问题显然出在 XTest 类的某个地方。您不禁想知道这是否与正在生成的编译器错误有关。

好吧,如果我们只注释掉导致编译器错误的那一行呢?你知道什么!代码编译执行得很好!

所以在不到一分钟的时间里,我们已经将罪魁祸首缩小到一行代码。我不会真正花时间去了解你所有代码的确切作用,但是,因为我认为您现在可以从这里开始,因为您确切地知道将精力集中在哪里。首先修复这些 IntelliSense 错误,然后查看您的代码是否在编译器不崩溃的情况下编译。

【讨论】:

请注意,“IntelliSense...”错误并不是真正的编译器错误,因为它们是由 IntelliSense 而不是编译器生成的。 Visual C++ 编译器和 IntelliSense 使用完全不同的前端,因此通常一个可能会报告错误,而另一个可能不会。 IMO 关于无效代码崩溃编译器的有趣之处不是代码无效,而是它使编译器崩溃:) @James McNellis:你说得对,它们并不是严格意义上的编译器错误,但在我看来,警告表明那行代码可能有问题,从我的测试来看,这就是案子。鉴于当时的情况,这至少应该让它们值得关注。 无论哪种方式,将代码降低到重现编译器错误/崩溃所需的最低限度可以使问题更易于阅读和一目了然。 另一个大图是编译器需要针对一套非常庞大的有效源代码进行测试,这些源代码会测试语言的每一个角落。但是没有一个测试套件可以声称它测试了所有可能的无效代码。【参考方案2】:

编译器作者不会高度重视修复编译器中不影响编译器从有效输入生成有效输出的能力的错误。在这些 bug 中,优先级最低的是那些不会静默产生无效输出的 bug。

因此,您的问题的答案很可能是因为此错误以前没有被报告过,或者被分配了非常非常低的优先级。

【讨论】:

我见过这类问题出现。例如,与 VS2013 一起编译的代码在与 VS2010 一起使用时会出现“内部(编译器文件'msc1.cpp',第 1420 行)”失败。无论如何,罪魁祸首将是 decltype 的使用,这几乎总是我看到 VS2010 出现此错误的原因

以上是关于为啥VC++ 2010编译器在编译简单代码时会崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Flutter 应用在​​ iOS 上启动时会崩溃?

为啥在网上找的一些c语言程序的代码在vc++6.0中编译总是出现错误?求指教

在VS2010的VC++中如何编译、链接、运行、调试程序

Webpack 在编译 typescript 代码失败时会导致 gulp watch 崩溃

为啥我安装的vc6.0之后,编译程序的时候总会出现这个图标呢?

为啥在Linux中strlwr()不能编译通过,已经查看过<string.h>,的确在头文件中没有