首页 > 解决方案 > 按值从局部变量返回初始化列表

问题描述

尝试执行以下操作时,我得到 free(): invalid size :

std::u32string FileMappingWrapper::getCurrCharPosAsString() const
{
    std::u32string progressString;
    size_t currLine = getFrameStartPos();
    while (currLine)
    {
        progressString.push_back(U'0' + currLine % 10);
        currLine /= 10;
    }
    return {progressString.rbegin(), progressString.rend()}; <- I expect that std::u32string rvalue constructor or RVO will be used
}

然后我从另一个调用这个函数:

void CurrFrameVisitor::visit(windows::NCursesProgressWindowDecorator *window)
{
    RawWindowBuffer newBuffer(window->getWindowDimensions().first, window->getWindowDimensions().second);
    auto progress = window->getParentWindowHandler()->getFileMapper()->getPrintedProgress();
    auto lineNo = window->getParentWindowHandler()->getFileMapper()->getCurrCharPosAsString();
    std::copy(progress.begin(), progress.end(), newBuffer[0].begin());
    newBuffer[0][progress.size()] = '%';
    if (lineNo.empty()) {
        lineNo.push_back(U'0');
    }
    std::copy(lineNo.begin(), lineNo.end(), std::next(newBuffer[0].begin(), progress.size() + 2));
    window->print(std::move(newBuffer)); <- All is good untill this point
}

我知道该示例无法编译,但这是我调试代码的内容,我可以看到调用访问者时一切都很好,直到堆栈展开。试图销毁从初始化列表创建的变量auto lineNo = window->getParentWindowHandler()->getFileMapper()->getCurrCharPosAsString();会引发 SIGABRT。所以我的问题是:从本地对象按值重新调整初始化列表是否像我所做的那样安全有效?谢谢

更新:

这是由于 newBuffer 数组不够大导致的错误。为什么然后 gdb 告诉 SIGABORT 是在销毁 lineNo 对象时?来自 gdb 的输出:

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff6c07801 in __GI_abort () at abort.c:79
#2  0x00007ffff6c50897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff6d7db9a "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007ffff6c5790a in malloc_printerr (str=str@entry=0x7ffff6d7bda0 "free(): invalid size") at malloc.c:5350
#4  0x00007ffff6c5ee2c in _int_free (have_lock=0, p=0x7fffec000dd0, av=0x7ffff6fb2c40 <main_arena>) at malloc.c:4161
#5  __GI___libc_free (mem=0x7fffec000de0) at malloc.c:3124
#6  0x000055555556b05e in __gnu_cxx::new_allocator<char32_t>::deallocate (this=<optimized out>, __p=<optimized out>) at /usr/include/c++/7/ext/new_allocator.h:125
#7  std::allocator_traits<std::allocator<char32_t> >::deallocate (__a=..., __n=<optimized out>, __p=<optimized out>) at /usr/include/c++/7/bits/alloc_traits.h:462
#8  std::__cxx11::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t> >::_M_destroy (__size=<optimized out>, this=0x7ffff68274a0) at /usr/include/c++/7/bits/basic_string.h:226
#9  std::__cxx11::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t> >::_M_dispose (this=0x7ffff68274a0) at /usr/include/c++/7/bits/basic_string.h:221
#10 std::__cxx11::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t> >::~basic_string (this=0x7ffff68274a0, __in_chrg=<optimized out>)
    at /usr/include/c++/7/bits/basic_string.h:647
#11 mirror::printer::CurrFrameVisitor::visit (this=<optimized out>, window=0x5555557c8040) at src/printer/CurrFrameVisitor.cpp:23 <- this is the line  auto lineNo = window->getParentWindowHandler()->getFileMapper()->getCurrCharPosAsString();

标签: c++11initializer-list

解决方案


推荐阅读