2012-11-26 2 views
2

Accelerated C++의 문제 12.1의 일부로 문자열 클래스의 구현을 수행하고 있습니다. 그것은 주로이 생성자의 : 보인다배열의 문자열 변환시 segfault

void Str::push_back(const char& c){ 
    if ((data + length) == limit){ 
     grow(); 
    } 
    unchecked_append(c); 
} 

grow()를 호출에 있지만 grow()의 신체를 실행하기 전에 문제를 일으킬 : back_inserterpush_back를 호출 할 때 문제를 일으키는 것으로 보인다

Str(const char* cp) { 
    std::copy(cp, cp+std::strlen(cp), std::back_inserter(*this)); 
} 

.

void Str::grow() 
{ 
    // when growing, allocate twice as much space as currently in use 
    size_type new_size = std::max(2 * (limit - data), ptrdiff_t(1)); 
    // allocate new space and copy existing elements to the new space 
    iterator new_data = alloc.allocate(new_size); 
    iterator new_avail = std::uninitialized_copy(data, (data+length), new_data); 

    // return the old space 
    uncreate(); 
    // reset pointers to point to the newly allocated space 
    data = new_data; 
    limit = data + new_size; 
} 

특히 "Str.exe가 작동을 멈췄습니다."라고 말하면 우분투는 세그먼트 오류를보고합니다. 분할 오류의 원인은 무엇

#ifndef _GUARD_STR_H 
#define _GUARD_STR_H 

#include <ctype.h> 
#include <memory> 
#include <iterator> 
#include <iostream> 
#include <cstddef> 
#include <cstring> 

class Str { 
    friend std::istream& operator>>(std::istream&, Str&); 
    public: 
     typedef size_t size_type; 
     typedef char * iterator; 
     typedef const char * const_iterator; 
     typedef char& reference; 
     typedef const char& const_reference; 
     typedef char value_type; 

     Str& operator+=(const Str& s){ 
      std::copy(s.begin(), s.end(), 
      std::back_inserter(*this)); 
      return *this; 
     } 

     // default constructor; create an empty Str 
     Str() { create();} 

     // create a Str containing n copies of c 
     Str(size_type n, char c){ } 

     iterator end() { return data + length; } 
     iterator begin() { return data; } 
     const_iterator end() const { return data + length; } 
     const_iterator begin() const { return data; } 

     // create a Str from a null-terminated array of char 
     Str(const char* cp) { 
      std::copy(cp, cp+std::strlen(cp), std::back_inserter(*this)); 
     } 

     template<class In> Str(In i, In j) { 
      std::copy(i, j, std::back_inserter(data)); 
     } 

     std::allocator<char> alloc; 

     void push_back(const char&); 

     char& operator[](size_type i) { return data[i]; } 
     const char& operator[](size_type i) const { return data[i]; } 
     size_type size() const { return length; } 

    private: 
     iterator data; 
     size_t length; 
     iterator limit; 
     void create(); 
     void create(size_type, char); 
     void grow(); 
     void unchecked_append(const char& c); 
     void uncreate(); 
}; 

void Str::push_back(const char& c){ 
    if ((data + length) == limit){ 
     grow(); 
    } 
    unchecked_append(c); 
} 

void Str::unchecked_append(const char & val) 
{ 
    alloc.construct((data+(length++)), val); 
} 

void Str::uncreate() 
{ 
    if (data) { 
     // destroy (in reverse order) the elements that were constructed 
     iterator it = (data + length); 
     while (it != data) 
      alloc.destroy(--it); 

     // return all the space that was allocated 
     alloc.deallocate(data, limit - data); 
    } 

    // reset pointers to indicate that the Vec is empty again 
    data = limit = 0; 
} 

void Str::create(){ 
    data = limit = 0; 
} 

void Str::create(size_type n, char c){ 
    data = alloc.allocate(n); 
    std::uninitialized_fill(data, data + n, c); 
} 

void Str::grow() 
{ 
    // when growing, allocate twice as much space as currently in use 
    size_type new_size = std::max(2 * (limit - data), ptrdiff_t(1)); 
    // allocate new space and copy existing elements to the new space 
    iterator new_data = alloc.allocate(new_size); 
    iterator new_avail = std::uninitialized_copy(data, (data+length), new_data); 

    // return the old space 
    uncreate(); 
    // reset pointers to point to the newly allocated space 
    data = new_data; 
    limit = data + new_size; 
} 

std::ostream& operator<<(std::ostream&, const Str&); 
Str operator+(const Str&, const Str&); 

std::ostream& operator<<(std::ostream& os, const Str& s) 
{ 
    for (Str::size_type i = 0; i != s.size(); ++i) 
     os << s[i]; 
    return os; 
} 

std::istream& operator>>(std::istream& is, Str& s) 
{ 
    char c; 
    while (is.get(c)){ 
     s.push_back(c); 
    } 
    return is; 
} 

Str operator+(const Str& s, const Str& t) 
{ 
    Str r = s; 
    r += t; 
    return r; 
} 

#endif 

:

여기 내 전체 코드입니까?

+1

디버거를 사용해 보셨습니까? 프로그램이 충돌하는 곳? –

답변

3

어디서나 length을 초기화하지 않는 것 같습니다.

+2

+1 사실 성장 및 복사 과정을 포함하여이 코드에서 * 아무 곳이나 * 길이가 할당되지 않지만 반복적으로 평가됩니다 – WhozCraig