반응형

C언어, Queue, pop() 구현하던 도중 shallow copy와

비슷한 문제 발생

 

내가 구현해본 pop은 첫번째 노드의 데이터를 리턴함과 동시에 Queue 에서 제거하는 함수로

1. char * Data 에 첫번째 노드 데이터를 복사하고 그걸 나중에 리턴한다 

2. Queue의 Head가 첫번째 노드의 다음 주소를 임시 노드에 담아둔다

3. 첫번째 노드를 free 해준다

4. Queue 사이즈 1 감소시킨다

5. 첫번째 노드에 임시노드에 적혀있던 주소를 담는다, 이로써 다음 노드가 첫번째 노드가 된다

6. 데이터를 리턴한다

 

그러나 1번 char * Data 에 첫번째 노드 데이터를 담고 그걸 나중에 리턴할때 쓰레기값 또는 이상한 값이 출력 됐다.

 

 

원인

데이터를 복사한게 아닌, 데이터(char 배열)의 주소를 복사하게 됐다

C++ 에서는 동일한 클래스 타입의 두개의 인스턴스가 존재할때 복사 생성자를 통해서, 인스턴스가 가지고 있는 데이터들을 다른 인스턴스에 복사할 수 있다, 문제는 이때 컴파일러가 만들어주는 기본 복사 생성자를 쓰게되면, 순수하게 데이터 변수들의 값만 복사하게 되고, 주소를 가지고 있는 타입도, 주소를 복사 하게 된다, 그리고 두개의 데이터가 동일한 주소를 가리키는 사태가 벌어진다. 이렇게 되면 원본이던 사본이던 간에 어느 한쪽이 소멸되어 주소가 사라지면, 복사 받은 쪽에서도 주소가 사라져서 결국 이상한 주소를 가리킨다.

그리고 실제로 196번 라인에서 _pQueue->pHead 의 메모리를 해제할때

_pQueue->pHead->data 조차 사라지며, 그걸 담아 뒀던 char* Data 도 사라진 주소를 가리켜 결국

이상한 주소를 가리키게 됐다

 

 

 

해결

pop의 인자로 배열을 input 으로 넣고 해당 배열에 data를 복사하도록, 그리고 주소를 대입하는게 아닌, strcpy_s를 사용해 실제 문자열을 복사하도록 했다

이후 pop한 데이터가 쓰레기 값을 출력하는 사태는 없어졌다.

 

반응형
반응형

Array vs LinkedList

Array(배열)

  1. 중간 삽입, 중간 삭제는 링크드 리스트에 비해서 어렵고 느림

  2. 삽입할 마다, 메모리 동적 할당 삽입을 하지 않기 때문에, 데이터를 삽입하는 속도는 링크드 리스트에 비해서 빠름

  3. 인덱스로 접근 가능 하므로, random access(무작위 접근, 비순차적 접근 가능), sequential access(순차적 접근) 할 필요 없음, 데이터의 위치에 관계없이 접근시간이 일정함

 

random access : 무작위 접근, 임의 접근, 비순차적 접근 이라고도 , 어떤 데이터를 기억장소에 기록하거나 거기에서 읽어 때에, 기억 장소에 관계 없이 동일한 접근 시간이 걸리는 접근 방식

 

sequential access : 순차적 접근, 데이터를 순차적으로 접근하는 방식, 데이터의 위치에 따라 접근 시간이 달라짐

 

 

LinkedList(링크드 리스트)

  1. 중간 삽입, 중간 삭제는 배열에 비해서 쉽고 빠름

  2. 삽입할 마다, 메모리 동적 할당으로 삽입을 하기 때문에, 데이터를 삽입하는 속도는 배열에 비해서 느림

  3. sequential access(순차적 접근) 가능, index 개념이 없음, random access 불가능, 데이터의 위치에 따라 접근 시간이 달라짐

반응형
반응형

member initializer list 사용시 주의

또다른 HEAP CORRUPTION DETECTED 문제 발생

컨테이너 클래스 vector 만들었는데

 

생성자 코드, member initializer list 를 통해 초기화

resize 함수에서 , 동적 할당된 배열이므로, delete[] m_pArray 했는데 HEAP CORRUPTION DETECTED 발생

 

원인

member initializer list 통한 초기화를 할때

m_iSze, m_iCapacity, m_pArray 순으로 초기화 되길 바랬지만, 컴파일러는 멤버 변수 선언 순서대로 초기화 한다, 그래서 m_pArray 부터 초기화를 했고 m_iCapacity 0값인 상태에서 m_iCapacity + 2 했으니 실상

2만큼의 크기를 가지는 배열을 초기화 한것

 

 

선언 순서를 바꾼뒤 다시 빌드했다

이후  이상 HEAP_CORRUPTION_DETECTED 런타임 에러가 발생하지 않았다.

 

 

결론

member initializer list 를 통한 멤버 변수 초기화를 할때는, 

 

생성자()

 : 순서1, 순서2, 순서3  // 이런순으로 초기화 되는게 아니라

{}

 

 

멤버 변수 선언 순서로 초기화를 하기 때문에 주의를 하자

반응형

+ Recent posts