【问题标题】:stack overflow with std::make_unique but not with raw pointer堆栈溢出 std::make_unique 但不是原始指针
【发布时间】:2015-02-04 22:44:20
【问题描述】:

我想分配一个大对象(bitset<1000000000>)。由于要避免拥有原始指针,我尝试了以下声明:

auto foo()->std::unique_ptr<std::bitset<MAX>>;
...
{
    auto bar = foo();
}

这会导致堆栈溢出错误(编译器是 VS2013)。但是

auto foo()->std::bitset<MAX>*;
...
{
    auto bar = foo();
    ...
    delete bar;
}

没有。

foo() 的实现如下:

auto is_prime = 
        //std::make_unique<std::bitset<MAX>>(std::bitset<MAX>{});
        // or:
        new std::bitset<MAX>{};
is_prime->set();

(*is_prime)[0] = (*is_prime)[1] = false;

auto max_i = static_cast<int>(std::sqrt(MAX)) + 1;
for (auto i = 1; i < max_i; i++) {
        if ((*is_prime)[i]) {
                for (auto j = i * i; j < MAX; j += i) {
                        (*is_prime)[j] = false;
                }
        }
}

return is_prime;

我错过了什么明显的东西?

【问题讨论】:

  • foo() 的实现是什么样的?
  • @BobFincheimer 我添加了它。它只是一个初筛,真的没有什么异国情调。
  • @dyp:我也是这么想的,然后意识到每个例子都是一个声明,后面跟着一个复合语句,大概在其他函数中。
  • @aschepler 刚看到,谢谢 :)

标签: c++ c++11 smart-pointers


【解决方案1】:
auto is_prime = 
   std::make_unique<std::bitset<MAX>>(std::bitset<MAX>{});

这一行在堆栈上创建一个临时位集对象 (std::bitset&lt;MAX&gt;{}),然后将其传递给堆上 new-ed 对象的复制构造函数。

要使用默认构造函数,您需要:

auto is_prime = std::make_unique<std::bitset<MAX>>();

【讨论】:

    【解决方案2】:

    当你使用

    typdef std::bitset<1000000> BS;
    std::make_unique<BS>(BS())
    

    您在堆栈上创建了一个相当大的对象:正在复制的临时对象!根据您在 tve 堆栈上已有多少或堆栈有多大,这可能很容易导致堆栈溢出。对于直接分配内存的操作,tge 栈上没有临时的。

    解决问题的简单方法是使用

    std::make_unique<BS>()
    

    因为这会导致调用堆分配对象的默认构造函数。

    【讨论】:

      猜你喜欢
      • 2016-08-17
      • 2012-08-31
      • 1970-01-01
      • 2014-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-15
      相关资源
      最近更新 更多