반응형

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한 데이터가 쓰레기 값을 출력하는 사태는 없어졌다.

 

반응형
반응형

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  // 이런순으로 초기화 되는게 아니라

{}

 

 

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

반응형
반응형

주의_1 while문 안에 switch를 사용할 때 

while문안에 if 문에서 break 하면 그뒤에 코드들은 거치지 않는다, 즉 if문은 원하는 지점에서 while문을 탈출 시킬 수 있다

위와 같이 while 안에 if 문을 써서 조건을 만족하면 break 문을 사용하여 while 문을 탈출 시킬수 있다

 

그런데 조건문중에 switch 문이 존재하고, while문과 switch 문을 아래와 같이 사용하면

while 안에 switch 안에 break 는 while 문을 탈출 시키지 못한다

break 문이 있다 치더라도, while문을 빠져나오지 못한다, 이유는 switch 안에 break문의 용도는

다음 케이스 문을 거치지 않고, switch문을 중단 시키는 용도 뿐이지, while문을 빠져나오진 못한다

 

해결책

빠져나오게 하고 싶다면, switch 문을 가장 마지막에 두고, switch 문의 case 만족할때

while문의 조건을 두고 있는 bool 변수를 false 시키는 것이다, 그러나, while 문안에 if, break 처럼

원하는 부분에서 중단 시킬 없다

 

switch를 가장 마지막에 두고 while 조건을 false로 바꾸면 가능하긴 하다 그러나 if 문처럼 원하는 지점에서 바로 탈출할 수 없다.

 

 

 

또는 return 문을 써서 switch 문도 while 문을 원하는 지점에서 바로 탈출 할 수 있기는 하지만 그와 동시에 전체 함수가 종료 된다.

 

반응형
반응형

EX02 HEAP CORRUPTION DETECTED

동적 할당을 하는 프로그램을 만들던 도중, free() 함수를 실행할때 에러 발생

 

원인:

Google 찾아보니, 할당한 영역을 벗어나서 접근하게 될경우 발생하는 에러 라고

 

 

 

 

/*Decoding        */

FileStreamInit(&fileStream, fileName, "r"); //파일크기에 따른 g_CodeSize 초기화

 

if (g_CodeSize == 0)

{

     printf("\nError, No data in codefile, zero codeSize\n");

     exit(1);

}

 

g_Buffer = (char*)calloc(g_CodeSize, sizeof(char));

fread_s(g_Buffer, g_CodeSize, sizeof(char), g_CodeSize, fileStream);

decode(g_Buffer, g_CodeSize);

 

아래 decode 함수에서  str[i] != '\0' 원인 이었음

i size 만큼만 i++ 해야 되는데, 범위를 넘어서 버린듯

 

 

 

해결:

void decode(char* str,size_t size)

{

     size_t i = 0;

     while( i < size )

     {

            str[i] -= 3;

            i++;

     }

}

 

결론: 파일 안에서 글자 수에 따른 범위를 정할때는 index < size 방식이 제일 안전함

반응형
반응형

EX01_읽기 엑세스 위반

 

 

 

원인 : 배열의 인덱스를 벗어난 주소를 찾아서, 금지된 영역에(kernal 영역) 엑세스 하려고 했기 때문에

 

해결 : 배열이 충분히 사이즈가 크게 만들던지, 배열을 가져오는 함수에서 제한 범위를 벗어나지 않게 해야 한다

반응형

+ Recent posts