다음과 같은 에러가 났다.
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h: In function ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2359: instantiated from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2714: instantiated from ‘void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
NR_stat.cpp:188: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2280: error: assignment of read-only location
사실 전체 에러 메세지는 훨씬 길다.
접기
[adnoctum@bioism source]$ g++ -c NR_stat.cpp
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h: In function ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2359: instantiated from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2714: instantiated from ‘void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
NR_stat.cpp:188: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2280: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h: In function ‘void std::__pop_heap(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Tp) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Tp = double]’:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2435: instantiated from ‘void std::partial_sort(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2630: instantiated from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Size = int]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2713: instantiated from ‘void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
NR_stat.cpp:188: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:237: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h: In function ‘void std::__unguarded_linear_insert(_RandomAccessIterator, _Tp) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Tp = double]’:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2283: instantiated from ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2359: instantiated from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2714: instantiated from ‘void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
NR_stat.cpp:188: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2232: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2236: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h: In function ‘void std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Distance = int, _Tp = double]’:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:364: instantiated from ‘void std::make_heap(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2432: instantiated from ‘void std::partial_sort(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2630: instantiated from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Size = int]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2713: instantiated from ‘void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
NR_stat.cpp:188: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:218: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:224: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algobase.h: In static member function ‘static void std::__iter_swap<_BoolType>::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _ForwardIterator2 = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, bool _BoolType = false]’:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algobase.h:163: instantiated from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _ForwardIterator2 = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2181: instantiated from ‘_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, _Tp) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Tp = double]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2642: instantiated from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Size = int]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2713: instantiated from ‘void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
NR_stat.cpp:188: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algobase.h:115: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algobase.h:116: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h: In function ‘void std::__push_heap(_RandomAccessIterator, _Distance, _Distance, _Tp) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Distance = int, _Tp = double]’:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:227: instantiated from ‘void std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Distance = int, _Tp = double]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:364: instantiated from ‘void std::make_heap(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2432: instantiated from ‘void std::partial_sort(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2630: instantiated from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _Size = int]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2713: instantiated from ‘void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
NR_stat.cpp:188: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:123: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:127: error: assignment of read-only location
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algobase.h: In function ‘_BI2 std::__copy_backward_aux(_BI1, _BI1, _BI2) [with _BI1 = const double*, _BI2 = const double*]’:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algobase.h:482: instantiated from ‘static _BI2 std::__copy_backward_normal<true, true>::copy_b_n(_BI1, _BI1, _BI2) [with _BI1 = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _BI2 = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algobase.h:517: instantiated from ‘_BI2 std::copy_backward(_BI1, _BI1, _BI2) [with _BI1 = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >, _BI2 = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2279: instantiated from ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2359: instantiated from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2714: instantiated from ‘void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double, std::allocator<double> > >]’
NR_stat.cpp:188: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algobase.h:443: error: no matching function for call to ‘std::__copy_backward<true, std::random_access_iterator_tag>::copy_b(const double*&, const double*&, const double*&)’
접기
정도가 될 것이고, 이것들은 stl_algo.h의 함수 void std::__insertion_sort 의 안에서 호출된 것일 것이다. 실제로 에러가 난 부분은 발췌된 에러 메세지의 가장 마지막 부분으로 stl_algo.h 파일의 2280 번째 줄에서
는 것이다. stl_algo.h 파일의 2280 번 근처의 소스 코드를 보면,
에러가 난 위치는 random access iterator에다가 값을 할당하고 있는 코드이다. 에러 메세지의 내용이 read-only 위치에 값을 할당하려고 했으므로 아마도 [__first]가 read-only 였을 것이다. 왜 그랬을까? 이것은 즉 [__first]가 const 로 넘어갔다는 의미이다. 실제로 NR_stat.cpp 파일의 188 번째 줄 근처를 보면,
std::sort 로 넘기는 [data1]이 const 로 넘어 왔음을 176 번째 줄에서 볼 수 있다. 이렇게 const 로 넘어 온 데이터를, const이면 동작을 진행할 수 없는 std::sort 함수로 넘겼기 때문에 에러가 발생한 것이다.
해결책은 간단하다. 값을 const가 아닌 형태의 call-by-reference나 call-by-value로 받는 것이다. 간단히는 함수의 prototype 에서 const 예약어를 제외하면 되겠지.
STL의 vector는 random access iterator를 제공한다. STL의 sort는 random access iterator를 입력으로 받아들인다. 따라서 위의 경우 iteartor type은 일치를 한다. 그러나 const 지정자가 주어지면서 read-only 형태로 되었기 때문에 sort에서 에러가 난 것이다. vector와는 달리 STL의 set 은 random access iterator 를 제공하지 않기 때문에 sort를 할 수 없다, set을 sort하는 것은 별로 의미도 없고, 일반적으로 sort가 되어 있는 형태로 유지되긴 하지만(하지만 보장할 수는 없겠지, 표준에 그렇게 하라고 되어 있지 않으니).
에러 메세지가 무지 길다고 미리 겁먹지 말자. 차근차근 따져 보면 무지 간단한 경우가 많고, 에러 메세지가 길다는 것은 에러의 원인을 찾아낼 수 있는 힌트가 그만큼 많다는 의미이다.