태그 : STL

삽질로 배우는 STL? 해답편 ... -_-

삽질로 배우는 STL 기초 개념? 의 解편입니다.

이전 글을 보시지 못한 상태에서 내가 스스로 코드의 버그를 밝혀내겠소 같은 생각을 하는 분이 계시...려나 모르겠군요. -_-;
그런 분은 이전 글만 읽어보시면 되겠습니다.



여튼 정답을, 자타공인 코딩의 신 아샬 님께서 매우 가볍게 맞추어 주셨습니다.
상품으로 특별히 제 블로그 1년 정기구독RSS를 증정!
필요 없다구요? 넵 지성 _-

아무튼 해설편입니다.
문제편의 소스 코드 전부를 인용...하지는 않겠습니다.
			AddData(vecFoo, p);
ASSERT(&p == &vecFoo[i]); //
p.dwType += 10;
힙 메모리가 깨지는 원인은 바로 저 부분에 있었습니다.
  1. Foo &p = vecFoo[i];로 벡터 내 원소 중 하나의 메모리를 직접 참조하고 있던 상황에서,
  2. vecFoo에 push_back이 이루어집니다.
  3. 기본으로 할당되어 있는 사이즈 이하일 때 추가되는건 아무 문제가 없는데,
    루프를 돌면서 벡터 크기가 더 커지게 되면서 vector STL이 할당 영역을 늘리는 작업을 시도하게 됩니다.
    물론 이때의 작업은 새로 더 많은 메모리를 할당해서 거기에 기존 데이터를 복사해넣고, 기존 할당 영역은 날려 버리는 것.
    이 작업이 일어나면서, &p가 가리키는 것은 더이상 vecFoo[i]가 아닌 엉뚱한, 이미 자연으로 돌아가 중천을 떠도는 무언가...가 되어버리는거죠. 그게 뭐 어쨌냐고 물으신다면 그저 웃을 수 밖에 없지만서도 뭐랄까,
    이를테면 자길 버리고서 더이상 아무 상관 없게 된 남편이 곧장 다시 와서는 '그래도 네가 필요해'라며 자신의 몸을 더듬으면, 님 같으면 기분 좋겠어여?!
    버릴땐 언제고 이제 와선 또 뭐하는거야, 어이 거기 내 힙 건들지말라구!! 하고 힙 에러를 내는 사랑과 전쟁...스러운 그런 가슴 아픈 스토리...가 펼쳐진 것을 목격한거죠 우리는... ... -_-;;

아무튼;;;
설령 힙 에러를 내지 않는다 하더라도, &p에 들어간 값은 vector가 메모리 재할당 작업을 하는 순간 근거를 알 수 없는 값이 되어버립니다. 그렇게 되면 코드는 문제 없이 넘어갔다 해도 왜 이상한 값이 난데 없이 들어가 있나 하고 골머리를 썩히는 그런 일이 생기게 될테지요, 그렇게 되면 왜 데이터가 이상해지는걸까 원인을 몰라 코드 전체를 쑤시고 다녔을...지도 모른다고 생각하니 조금 무섭다... -_-;;;

아무튼 이 사건은 vector, deque은 포인터 덜 신경 써도 되니 좋은 것 같넹, 이라고 생각하고서 생각 없이 STL에 기대다가 보기 좋게 당한 꼴보기 좋은 케이스였습니다.
vector나 deque 같은 계열은 배열내 원소들의 수가 늘거나 줄어들거나 하는 경우 운 좋게 무효가 되지 않는 경우도 있지만 대부분 무효가 될거라고 상정해두고서 작업하는 것이 좋을 것 같습니다. 특히 멀티 스레드 기반 프로그램이라면 벡터 원소에 대한 포인터를 걸어놓고서 먼 미래에 참조하는, 그런 일이 생기지 않도록 더욱더 조심해야겠지요.


아 간만에 어딘지 모르게 영양가 있어 보이는 글을 적어보았더니 기분이 좋근영. ( -_-)
영양가 있는 부분이 어딘지 모르겠다... 는게 문제지만. ( -_-);;;;

by nvu | 2007/12/28 10:34 | 트랙백 | 핑백(1) | 덧글(2)

삽질로 배우는 STL 기초 개념?

제목이 낚시...인듯한데 생각나는 제목이. -_-;

다음은 버그가 있는 코드입니다. 버그의 원인을 찾아보세요.
inline void AddData(vector<Foo>& vn, Foo& fu) 
{
vn.push_back(fu);
}

{
vector<Foo> vecFoo;
//...
//적당히 vecFoo에 개체를 채워넣는다.
//
size_t n = vecFoo.size();
for (size_t i = 0; i < n; ++i) {
Foo &p = vecFoo[i];
if (p.dwType < 10) {
AddData(vecFoo, p);
p.dwType += 10;
}
}
}

분명, 테스트할 때만 해도 아무 문제 없던 프로그램.
그런데 실제로 프로그램이 실무에 들어가자 프로그램이 죽어버리는 치명적인 에러 발생.
확인해보니 테스트 때 vecFoo에 들어있는 개체 수를 500개 정도 넣어두고 저 루프에 들어가면 아무 문제가 없는데, 몇개라고 단정 지어 말할 수는 없지만 일정 갯수... 그러니까 한 600개 쯤? 이상이 되니 힙이 깨지는 에러가 발생하는 것이었다.

도대체 나는 무엇을 잘못한 것일까요?

힌트 :
vecFoo를 선언한 후, vecFoo.reserved(10000); 식으로 미리 vecFoo에 들어갈 최대갯수 이상으로 영역을 넉넉하게 할당해보니 문제가 발생하지 않았음.
하지만 이게 궁극적인 해결책이라고는 보이지 않는데에에...?



음음; 먼 예전에 짜놓고는 오늘에야 힙 깨지는거 확인하고 수정한 버그였습니다. 그래도 원인을 금방 찾아냈으니, 기분은 상큼.
뭐. 인터넷이란건 참 좋은 것 같습니다.
굳이 게시판에 질문을 적지 않더라도 조금만 머리 굴려 검색해보면 문제의 실마리를 찾아낼 수 있으니까요.

... 아무튼 오늘의 삽질 로깅이었습니다.

정답은 다음 이시간에! ... 랄까 음 저와 비슷한 경험 하신 분이 계실 것 같기도 한데 말이죠.

by nvu | 2007/12/27 14:25 | 트랙백 | 핑백(2) | 덧글(4)

◀ 이전 페이지          다음 페이지 ▶