Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么std::字符串分配两次?_C++_C++11 - Fatal编程技术网

C++ 为什么std::字符串分配两次?

C++ 为什么std::字符串分配两次?,c++,c++11,C++,C++11,我为std::string和std::vector编写了一个自定义分配器,如下所示: #include <cstdint> #include <iterator> #include <iostream> template <typename T> struct PSAllocator { typedef std::size_t size_type; typedef std::ptrdiff_t difference_type;

我为
std::string
std::vector
编写了一个自定义分配器,如下所示:

#include <cstdint>
#include <iterator>
#include <iostream>

template <typename T>
struct PSAllocator
{
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;

    template<typename U>
    struct rebind {typedef PSAllocator<U> other;};

    PSAllocator() throw() {};
    PSAllocator(const PSAllocator& other) throw() {};

    template<typename U>
    PSAllocator(const PSAllocator<U>& other) throw() {};

    template<typename U>
    PSAllocator& operator = (const PSAllocator<U>& other) { return *this; }
    PSAllocator<T>& operator = (const PSAllocator& other) { return *this; }
    ~PSAllocator() {}


    pointer allocate(size_type n, const void* hint = 0)
    {
        std::int32_t* data_ptr = reinterpret_cast<std::int32_t*>(::operator new(n * sizeof(value_type)));
        std::cout<<"Allocated: "<<&data_ptr[0]<<" of size: "<<n<<"\n";
        return reinterpret_cast<pointer>(&data_ptr[0]);
    }

    void deallocate(T* ptr, size_type n)
    {
        std::int32_t* data_ptr = reinterpret_cast<std::int32_t*>(ptr);
        std::cout<<"De-Allocated: "<<&data_ptr[0]<<" of size: "<<n<<"\n";
        ::operator delete(reinterpret_cast<T*>(&data_ptr[0]));
    }
};
那么,为什么它要为
std::string
分配两次和更多字节呢


我在Windows 8上使用的是g++4.8.1 x64 sjlj from:。

我无法复制双重分配,因为显然我的libstdc++根本没有为空字符串分配任何内容。不过,resize确实分配了26个字节,gdb帮助我识别:

因此,内存主要用于此表示,而此表示又由以下数据成员组成:

size_type    _M_length;   // 8 bytes
size_type    _M_capacity; // 8 bytes
_Atomic_word _M_refcount; // 4 bytes
我猜最后四个字节只是为了对齐,但我可能遗漏了一些数据元素

我猜这个
\u Rep
结构在堆上分配的主要原因是,它可以在字符串实例之间共享,也许还可以避免空字符串,因为我的系统上没有第一次分配


要了解为什么您的实现没有使用这种空字符串优化,请查看。它的实现似乎取决于
\u GLIBCXX\u FULLY\u DYNAMIC\u STRING
的值,该值在您的设置中显然不是零。我不建议直接更改该设置,因为它以下划线开头,因此被认为是私有的。但是您可能会发现一些公共设置会影响此值。

这在很大程度上取决于您正在使用的实现,您应该提供什么库实现和版本(如果您没有指定与默认实现不同的实现,通常是编译器+版本)'new cstring()'调用分配器一次,以及'str->resize(1)引用另一个例子,我同意DavidRodríguez dribeas所说的。也,。我的建议是,您在调试器中运行程序,并验证分配来自何处。您是否打算通过将
allocate
中返回的指针偏移8字节来在分配器中构建缓冲区溢出?在我的g++config.h中,它说:
/*如果需要完全动态的基本字符串,请定义为1,0禁用,未定义平台默认值*/#定义_GLIBCXX_完全_动态_字符串1
将其设置为0确实可以解决此问题!我尝试在代码块的链接器设置中使用
--禁用完全动态字符串
,但没有。。我把它输入到编译器选项中,它显然是无效的。所以我在配置中将它改为0:l起作用,但我不确定它会有什么副作用。。它还要求我的分配器具有
==
=明确定义的运算符。
Allocated: 0x3560a0 of size: 25
Allocated: 0x3560d0 of size: 26
De-Allocated: 0x3560a0 of size: 25
De-Allocated: 0x3560d0 of size: 26




Allocated: 0x351890 of size: 1
De-Allocated: 0x351890 of size: 1
size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
                   (     1     + 1) *     1          +     24
size_type    _M_length;   // 8 bytes
size_type    _M_capacity; // 8 bytes
_Atomic_word _M_refcount; // 4 bytes