2011-12-27 3 views
1

question regarding stack allocated stringstream storage에 대한 응답으로 @BenVoigt의 제안에 따라 stack_allocator (코드는 아래 참조)를 디자인하고이를 사용하여 basic_ostringstream 유형을 선언했습니다.사용자 지정 STL 할당자가 첫 번째 문자를 삭제합니다.

그래도 이상한 버그가 발생합니다. 결과 문자열을 출력 할 때 스트림에 배치되는 첫 번째 문자가 생략됩니다!

template<typename T, size_t capacity, size_t arr_size> 
__thread bool stack_allocator<T, capacity, arr_size>::_used[arr_size] = {}; 

template<typename T, size_t capacity, size_t arr_size> 
__thread T stack_allocator<T, capacity, arr_size>::_buf[capacity][arr_size] = {}; 

typedef std::basic_ostringstream<char, 
           std::char_traits<char>, 
           stack_allocator<char, 1024, 5> > stack_ostringstream; 
int main() 
{ 
    stack_ostringstream _os; 
    _os << "hello world"; 
    std::cout << _os.str() << std::endl; 
    return 0; 
} 

결과 출력은 다음과 같습니다 : 여기

은 예입니다

여보세요 세계

사람이 첫 번째 문자에 무슨 일이 일어나고 있는지에 정교한 수 있습니까? 그것은 꽤 단순, ​​난 개선의 여지가 많이있다 확신 당신이 할당 할 경우

#include <cstddef> 
#include <limits> 
#include <bits/allocator.h> 

template<typename T, size_t capacity = 1024, size_t arr_size = 5> 
class stack_allocator 
{ 
public: 
    typedef T value_type; 
    typedef value_type* pointer; 
    typedef const value_type* const_pointer; 
    typedef value_type& reference; 
    typedef const value_type& const_reference; 
    typedef std::size_t size_type; 
    typedef std::ptrdiff_t difference_type; 

    inline explicit stack_allocator() { } 
    template<typename U> 
    inline explicit stack_allocator(const stack_allocator<U, capacity, arr_size>& that) { } 
    inline ~stack_allocator() {} 

    template<typename U> 
    struct rebind 
    { 
    typedef stack_allocator<U, capacity, arr_size> other; 
    }; 

    inline pointer allocate(size_type cnt, typename std::allocator<void>::const_pointer = 0) 
    { 
    if (cnt > capacity) 
     return reinterpret_cast<pointer>(::operator new(cnt * sizeof (T))); 
    for (size_t i = 0; i < arr_size; ++i) 
    { 
     if (!_used[i]) 
     { 
     _used[i] = true; 
     return reinterpret_cast<pointer>(_buf[i]); 
     } 
    } 
    } 

    inline void deallocate(pointer p, size_type) 
    { 
    for (size_t i = 0; i < arr_size; ++i) 
    { 
     if (p != _buf[i]) 
     continue; 
     _used[i] = false; 
     return; 
    } 
    ::operator delete(p); 
    } 

    inline pointer address(reference r) { return &r; } 
    inline const_pointer address(const_reference r) { return &r; } 

    inline size_type max_size() const 
    { 
    return std::numeric_limits<size_type>::max()/sizeof(T); 
    } 

    inline void construct(pointer p, const T& t) { new(p) T(t); } 
    inline void destroy(pointer p) { p->~T(); } 

    inline bool operator==(const stack_allocator&) const { return true; } 
    inline bool operator!=(const stack_allocator& a) const { return !operator==(a); } 

private: 
    static __thread bool _used[arr_size]; 
    static __thread T _buf[capacity][arr_size]; 
}; 

답변

3

귀하의 allocate 기능은 끝을 떨어질 수 :

stack_allocator의 IMPL

다음 (버그를 수정 견딜하지를!) arr_size 이상입니다. g++ -Wall을 사용하면 이러한 종류의 경고 메시지가 표시됩니다.

다른 문제는 _buf 배열 색인이 거꾸로 있다는 것입니다. static T _buf[arr_size][capacity];이어야하며, 첫 번째 색인이 될 원래 코드에있는 다른 순서가 아니라 행으로 arr_size이 있어야합니다.

또한 부수적으로, _으로 시작하는 식별자를 피하십시오. 이러한 식별자 중 일부는 구현을 위해 예약되어 있으므로 정확한 규칙을 기억하는 것보다 사용하기가 쉽습니다. 마지막으로 bits/ 헤더를 직접 포함하지 마십시오. 실제 헤더 만 사용하십시오. 이 경우 memory입니다. 또한 컴파일하려면 <iostream><sstream>에 대한 포함 사항을 추가해야했습니다.

관련 문제