StackString的Chromium堆栈容器无法工作(至少在Visual C ++中)

问题描述 投票:0回答:1

症状

我正在调查使用铬stack_container专门设置StackString。我用以下方法制作了一个测试程序:

#include <chromium/base/stack_container.h>
int main() {
    StackString<300> s;
    return 0;
}

这应该在堆栈上创建空间,字符串将保留此空间。

我很惊讶地发现,当我在allocate中向StackAllocator添加一些断点时,堆栈缓冲区永远不会返回给任何人。即,通用分配器始终被调用:

pointer allocate(size_type n, void* hint = 0) {
    if (source_ != NULL && !source_->used_stack_buffer_
        && n <= stack_capacity) {
      source_->used_stack_buffer_ = true; // source_ is always NULL
      return source_->stack_buffer();     // and so this is never returned.
    } else {
      return std::allocator<T>::allocate(n, hint); // This is always called.
    }
}

问题

经过进一步调查,我发现这是因为当创建std::basic_string类型时(作为StackString构造的一部分),VisualC ++实现将分配器存储到某些对中。然后当需要使用它时,它将其复制到代理中:

void _Alloc_proxy()
    {   // construct proxy
    typename _Alty::template rebind<_Container_proxy>::other
        _Alproxy(_Getal()); // Copies the allocator!
    _Myproxy() = _Unfancy(_Alproxy.allocate(1)); // NOTE this for a later point.
    ...

StackAllocator的拷贝构造函数将拷贝堆栈指针设置为NULL。因此StackString永远不会工作。

此外,如果StackStringdidnt有这个问题,它立即分配1的空间,这意味着在你添加任何东西之后,它会迅速增长并且无论如何都会遇到同样的问题。

问题

  1. 这是一个错误,如果是这样的话,VisualC ++还是铬?
  2. 如果没有出现第一个症状,那么第二个项目不会成为大多数编译器的问题吗?
c++ string stack
1个回答
0
投票

似乎StackString已从Chromium项目中移除:https://bugs.chromium.org/p/chromium/issues/detail?id=709273

但这不是一个错误,而是对一个小字符串进行某种优化。

当在“Debug”中编译时,Visual Studio 2015/2017将在堆中分配一个16字节的std :: _ Container_proxy,即使对于空字符串也是如此。在“Release”中,我们不会将堆内存用于StackString。

我用这段代码测试了它:

#include <iostream>
#include <new>
#include "stack_container.h"

std::size_t memory = 0;
std::size_t alloc = 0;

void* operator new(std::size_t s) throw(std::bad_alloc) {
    // Put breakpoint here
    memory += s;
    ++alloc;
    return malloc(s);
}

void operator delete(void* p) throw() {
    --alloc;
    free(p);
}

void PrintMem_Info()
{
    std::cout << "memory = " << memory << '\n';
    std::cout << "alloc = " << alloc << '\n';
}

int main()
{
    StackString<256> str;
    PrintMem_Info();
    str->append("Hello World!");
    PrintMem_Info();
    str[0] = '1';
    str[1] = '2';
}

我的解决方案是:

pointer allocate(size_type n, void* hint = 0) {
#if defined(_MSC_VER)
    if (n > stack_capacity)
    {
        n = stack_capacity;
    }
#endif // if defined(_MSC_VER)
    if (source_ != nullptr && !source_->used_stack_buffer_
        && n <= stack_capacity) {
        source_->used_stack_buffer_ = true;
        return source_->stack_buffer();
    }
    else {
        return std::allocator<T>::allocate(n, hint);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.