insert 함수를 오버라이딩 했는데, 삽입시 약간의 문제가 발생합니다.
글쓴이: dltkddyd / 작성시간: 금, 2014/05/16 - 4:59오후
siterator insert(siterator position, const value_type& val) { if(position.pointer()==NULL) {return NULL;} if(convertItToIdx(position)==-1) { return NULL; } if(deque<PTRTYPE>::size()==0) {return NULL;} ssize_type num=&(*this)[deque<PTRTYPE>::size()-1]-position.pointer()+1; ssize_type idx=position.pointer()-&(*this)[0]; cout<<"idx "<<idx<<" num "<<num<<endl;//test deque<PTRTYPE>::resize(deque<PTRTYPE>::size()+1); cout<<deque<PTRTYPE>::size()<<endl;//test memmove(&(*this)[idx+1], &(*this)[idx],sizeof(value_type)*num);//이 부분에서 일단 제대로 옮겨지지 않습니다. memset(&(*this)[idx],0,sizeof(value_type));//그리고 이걸로 포인터의 연결고리를 끊으려 했는데(이중 커럽션을 방지하기 위해), 마지막에 double corruption 오류가 발생합니다. //clear((*this)[idx]); (*this)[idx]=val; cout<<"insert 1"<<endl;//test return &(*this)[idx]; }
이 문제 어떻게 해결해야 하나요?
추후 더 살펴보니 이 문제가 operator=에 영향을 또 주는군요. 대입연산자는 다음과 같이 정의했습니다.
sdeque<value_type>& operator=( const typename senable_if<is_sdeque<typename senable_if<!is_ssdeque<type>::value,type>::type2>::value,type>::type2& right ) {//This copys deeply in case of 1 dimession if(deque<PTRTYPE>::size()!=0) { deque<PTRTYPE>::clear(); } deque<PTRTYPE>::resize(right.size()); if(is_class<type::value_type>::value==0) { memcpy( &(*this)[0], &right[0], sizeof(value_type)*right.size() );//trouble } else { for(unsigned long int i=0;i<right.size();i++) { (*this)[i]=right[i];//trouble } } return *this; }
그리고 main은 다음과 같고요.
int main() { sdeque<sdeque<unsigned long int>> obj33(3,2); obj33( 2,4,6,8,10,12 ); sdeque<unsigned long int> obj34(2); obj34(25,26); obj33.insertA(obj33.end()-1,obj34);//여기서 문제가 발생하기 시작해서 cout<<obj33.size()<<endl; for(unsigned long int i=0;i<obj33.size();i++) { for(unsigned long int j=0;j<obj33[i].size();j++) { cout<<obj33[i][j]<<" "; } } return 0; }
그러고 보니 질문할 내용의 코드를 제대로 올리지 않았었군요. 이거 새롭게 편집해서 올린 내용입니다.
Forums:
에러가 날 때마다 하나하나 질문 다시기 전에 디버거
에러가 날 때마다 하나하나 질문 다시기 전에 디버거 사용 방법을 익히시길 추천합니다.
그리고, 사람들이 답글을 달면 좀 읽고 생각해보셨으면 좋겠습니다.
질문의 내용 그 자체보다.
그 질문의 본질이 무엇인지 아시고 답변 주셨으면 좋겠습니다.
과연 내부의 포인터가 무엇이냐는 내용이 포함된 질문이었습니다. 뭔가 어긋나고 있다고 추정되는데, 그게 경험이 부족한 고로 질문드린 겁니다. 전의 내용하고는 다른 질문이었습니다.
본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.
그러니까 디버거를 쓰시라는 겁니다. 뭔가 어긋나고
그러니까 디버거를 쓰시라는 겁니다. 뭔가 어긋나고 있다고 추정만 하고 질문하지 마시구요.
지금까지 올리신 질문 중에 상당수의 질문이 디버거를 돌려봤으면 올리지 않으셨을 질문으로 보입니다.
디버거를 돌려봤으면 '왜 이렇게 동작하나요?'의 질문이 올라와야 정상이지 '왜 에러가 나나요?'의 질문이 올라올수는 없거든요.
아마도 지금껏 질문에 원하는 대답을 얻으셨던 적이 별로 없으셨지 싶은데, 왜 그런지 한번쯤 생각해보셨으면 좋겠습니다.
글쎄, 그런적은 없었습니다.
지금의 답변 글 빼고는 원하는 답변들을 하시더군요. 그리고 제가 짐작했던(확신이 서지 않아서 올린 질문글) 것과 같은 답변이 올라온 적도 있었고요. 디버거 돌린다고 딱히 오류가 원지를 알 수가 없죠. 디버거가 오류가 발생한 지점만 알려주지, 뭐가 문제인지를 알려주는 것은 아니죠. 이건 정말 답답한 디버거입니다. 디버거로 찾을 수 있는 문제라면 디버거로 찾아야겠지만, 디버거가 알려주는 것이라는 너무 제한적입니다. 결국 원인은 본인이 찾아야 되는 거고요. 이거 돌렸어도 딱히 뭐가 문제인지 알 수가 없군요. 제가 만들지 않은 코드도 나오고. 머리만 복잡해지는 듯합니다.
본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.
그럼 그 머리 복잡한것을 왜 다른사람에게 전가하나요?
그럼 그 머리 복잡한것을 왜 다른사람에게 전가하나요? 그런거에 머리가 복잡해 진다면 님이 제대로 C++공부를 안했다는 뜻이죠. 만약 C++을 제대로 알고 있고, 그 상태에서 디버깅을 한다면 최소한 문제가 뭔지는 알고 질문을 해야하는겁니다. 질문들 계속 보고 있다 보면 C++기본 개념을 잘 이해 못하시고 계신 상태에서 자꾸 이상한 프로그램을 짜려고 하니 문제가 발생하는 것 같습니다.
C++기본서부터 다시 보시고, The C++ programming language라던가, Effective C++이라던가 정도는 보시고 다시 오시면 친절한 답변이 달릴거라 기대합니다. 저도 글쓴분이 질문하신 그에 답변 몇번 달았지만 그건 그냥 지나가던 길에 친절을 베푼 정도지, 전혀 같이 고민해서 답변을 다는 수준은 아니었습니다. 그런데 질문 수준이 딱 초급자 수준을 몇달동안 벗어나지 못한다면, 아직 답변 다는 분들이 매우 친절하신겁니다.
무슨 답변을 달았길래 그러죠?
님이 답변 단 글 기억이 안 나는데요. 기억이 안 나는 것인지, 님이 달지 않은 것인지? 그리고 전가한 적 없습니다. 답변 달기 싫으면 답변 안 달면 그만인 것이죠? 질문과 답은 상호적인 것이지 누가 누구에게 일방적으로 도움을 주는 것이라고만 생각하지 않기에 드리는 말씀입니다. 전혀 쌍방향적이지 않은 사고방식을 가지셨군요. 실력이 없으니 답변 할 건더기도 없겠군요.
본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.
아.. 이 답글이 보니 짜증이 마구 나네요. 누가
아.. 이 답글이 보니 짜증이 마구 나네요. 누가 누구에게 일방적으로 도움을 주게 만든건 님 자신입니다. C++ 조금이라도 아는 사람들은 님이 저런식으로 insert를 오버라이딩 하려는거 보면 그냥 뒷골이 땡기게 됩니다. 그거 참고 답글 달아주는 사람들이 대단한거고, 계속 저런식으로 쓰지 말라고 하는데 끝까지 혼자 저렇게 구현하면서 계속 질문만 양산하고 있는 사람이 님 자신이라고요.
그리고 문법책 다시 보라고 조언도 하고, 읽을 책 추천도 해 주었는데 이런말 들으니 정말 싫네요. 혼자 잘 사시길 바랍니다.
이분글에 꾸준히 답글다는 분들 참 대단하신듯.
이분글에 꾸준히 답글다는 분들 참 대단하신듯.
디버거 실행해보셨는지?
문제가 뭔지 아십니까? 알고 이런 말을 하는건지, 모르니까 이런 식으로 얼버무리는 건지 궁금한데요? 저런 식으로 표준을 오버라이딩 하지 말라는 충고는 들었습니다. 그런데 만약 저 insert 함수를 insert가 아닌 다른 insertA 라는 식으로 이름을 바꾸었을 때에도 동일한 문제가 발생합니다. 설사 멤버로 컨테이너 객체를 둔다 할지라도 memset, memmove를 사용하면 저런 동일한 문제가 생깁니다. 이 문제는 충고를 주셨던 문제하고는 다른 문제로 보이는데요.
답변주신대로 디버거 해봤더니 조금 문제가 있는 것으로 보이는 부분이 나오긴 나오더군요.
마지막 부분에서
return 0;
이 두 번 반복됩니다. 또 다른 문제가 있는지는 디버거 봐야 알 것 같습니다. 분명 return 0은 한 번 언급했는데요.
본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.
지금은 또 실행도중에 중지되네요.
지금은 또 실행도중에 중지되네요.
본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.
Deque는 내용을 순서대로 저장한다는 보장이 없습니다
http://www.cplusplus.com/reference/deque/deque/
> But, unlike vectors, deques are not guaranteed to store all its elements in contiguous storage locations: accessing elements in a deque by offsetting a pointer to another element causes undefined behavior.
그러니까 deque에 저장된 element의 주소를 이용해서 memmove를 하는 것은 정의되지 않은 동작입니다.
(보충): 심지어 deque가 아닌 vector라 해도 memmove/memcpy로 내용을 옮기는 것은 element type이 POD (plain old data)일 경우에만 가능합니다. (이 부분은 제가 전문가가 아니라서 용어가 부정확할 수도 있는데, 간단히 말하면 int, double, 포인터, 기타 이들만을 이용한 struct까지는 가능하지만 object를 생성/해제할 때 생성자/소멸자를 부르는 모든 클래스는 (다른 deque/vector 포함) 이런 사용이 불가능합니다. string만 해도 이런 식으로 쓸 때 프로그램이 제대로 동작할 거라는 보장이 없습니다.)
덧붙이자면
Corruption이란 건 프로그램에 버그가 있어서 덮어써서는 안되는 메모리를 덮어썼을 때 쓰는 표현입니다. 따라서 double corruption이란 말은 의미가 없으므로 (메모리를 한번 깨먹으나 두번 깨먹으나...) 일반적으로 쓰지 않습니다.
그런데 이상하게도..
offset을 통해 계산한 idx와 num은 정확히 계산이 됩니다. 그렇다면 문제는 저 idx와 num 때문에 memmove에 이상이 발생하는 것이 아니라 memmove에서 이상이 발생하는 것이라는 말씀이시죠? memmove를 삼가해야 겠군요. 감사합니다.
본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.
...
아직 C와 C++의 철학에 익숙하지 않으신 것 같은데, 이 언어들은 "프로그램을 제대로 짰을 때 제대로 된 결과가 나온다"만 보장하지 "틀리게 짰을 때 틀린 결과가 나온다"를 절대 보장하지 않습니다.
다시 말해 idx와 num이 "정확히" 계산이 되었다는 느낌이 든다면 그건 그냥 오늘 운이 좋은 겁니다.
(아니, 버그가 있는 코드를 버그를 발견하지 못하고 넘어가는 셈이니 운이 나쁘다고 해야 할지도...)
명세와 구현의 차이를 염두에 두고 공부해 보세요.
명세와 구현의 차이를 염두에 두고 공부해 보세요. 중요합니다.
명세에서 정의되지 않은 것은 구현마다 달라질 수 있습니다.
이왕이면, 다른 환경의 컴파일러나 라이브러리들에서도 돌려서 직접 비교해보세요.
---
http://coolengineer.com
모르면서 아는척이 너무 심해서 별로 대답해주고 싶지
모르면서 아는척이 너무 심해서 별로 대답해주고 싶지 않네요.
정상적인 대답을 해줘도 반발만 하니 답이 없습니다.
무슨 반말을 했다는 것인지?
익명성 뒤에 숨어서 함부로 험담하지 말기 바랍니다. 모르면서 아는 척 하는 그쪽이 답변을 안 하는 것이 도움이 되겠군요. 무슨 반말을 했다는 것인지? 실력이 안되니까 괜한 인신공격이나 하는 한심한 잡류로 보입니다.
본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.
한글을 잘 읽으세요. 반말이 아니라 반발입니다. 지금
한글을 잘 읽으세요.
반말이 아니라 반발입니다.
지금 당신이 하고 있는걸 반말이 아니라 반발이라고 합니다.
아이디가 없어서 익명입니다 확언하건데 아이디가 있어도
아이디가 없어서 익명입니다
확언하건데 아이디가 있어도 똑같이 적었을겁니다
남이 시간내서 뭔가 알려주면 따지기전에 자료부터 찾아보세요
댓글에 달린 글자도 제대로 못읽는데 자료 잘찾아볼 것 같지는 않지만 말이죠
댓글 달기