【问题标题】:How to avoid "compiler limit: compiler stack overflow" with large vector inits?如何避免带有大向量初始化的“编译器限制:编译器堆栈溢出”?
【发布时间】:2015-06-24 14:10:53
【问题描述】:

在我的单元测试中,我收到以下编译器错误:

 The error message indicates as follows: 
 'fatal error C1063: compiler limit: compiler stack overflow'

这是由一些生成的标头引起的,其中包含:

std::vector<unsigned char> GetTestData()
{
     return { 0x1, 0x2, 0x3 }; // Very large 500kb of data
}

如何以这种方式使用向量而不会使 MSVC 崩溃?请注意,代码在 clang 和 gcc 中构建正常。

【问题讨论】:

  • 500k 的整数字面量?
  • 你为什么不通过将数据添加到函数内的向量来做理智的事情,从而只返回向量?
  • 我猜它不应该在代码中。你不能将数据序列化到外部文件并在运行时以块的形式反序列化它吗?我认为这是最好的方法..
  • 我将它添加到代码中以避免进行文件 I/O,它仅在单元测试中具有硬编码的示例数据

标签: c++ visual-c++


【解决方案1】:

尝试将数据放入 const 静态数组,然后使用向量的范围 ctor:

std::vector<unsigned char> GetTestData()
{
    static const unsigned char data[] = { 
        0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0,
             ...
    }; // Very large 500kb of data

    return std::vector<unsigned char>(data, data + sizeof(data));
}

编辑:感谢 Lundin 指出 const。

【讨论】:

  • 你的答案胜过 Marks,因为没有 static 关键字,编译需要 1 小时!
  • 一个选项可能是在运行时生成数据,而不是对每个条目进行硬编码
  • @paulm 如果这是一个 Windows 程序,那么正确的做法是将数据放在程序的资源中并从这些资源中填充向量。查看RCDATA 及其用途。
  • 实际上应该是static const,因为.rodata.data更不可能溢出。
  • @PaulMcKenzie 该程序是多平台的,所以我无法使用资源
【解决方案2】:

尝试构建一个大数组进行初始化,而不是直接使用初始化器。

std::vector<unsigned char> GetTestData()
{
     static const unsigned char init[] = { 0x1, 0x2, 0x3 }; // Very large 500kb of data
     return std::vector<unsigned char>(std::begin(init), std::end(init));
}

【讨论】:

  • 这很容易溢出运行时堆栈,不是吗?
  • 确实如此。不让它static const只会将堆栈溢出从编译器移动到应用程序......
【解决方案3】:

即使它在 clang 和 gcc 中构建良好,我也不建议按值返回像这样的大向量。如果您正在处理的数据是不可变的,我会将其作为 const 引用返回,例如:

// EDIT Moved vector outside of function
static const std::vector<unsigned char> static_v({ 0x1, 0x2, 0x3 });
    const std::vector<unsigned char> & GetTestData()
    {
    return static_v;
    }

【讨论】:

  • 依赖移动操作有什么问题吗?他们已经正式成立 4 年了。
  • @Angew 绝对没有。但是返回一个静态常量引用至少可以保证耗时的 vector<...> 构造函数只被调用一次。如果您需要一个可变向量<...>,您可以稍后调用vector&lt;...&gt; vv = GetTestData(),它会生成一个(耗时的)时间副本并为您调用移动语义。
  • 由于某种原因,这样做仍然会使编译器崩溃
  • @Oncaphillis 很公平。
  • @paulm 那是因为在这种情况下解析器和编译器的工作基本相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-14
  • 2018-09-07
  • 2012-01-19
  • 1970-01-01
  • 2014-04-13
  • 2010-11-30
  • 2018-04-10
相关资源
最近更新 更多