본문 바로가기

Programming/C language

chapter 11. 메모리와 포인터 (내용요약 - 2)

동적할당


Memory <- OS가 관리 

user가 request -> '허가' 해준다. 


Heap영역 할당(허가) 받는다. => 사용 후 반환을 '반드시' 해야한다. 



malloc() 을 통해 memory 사용을 허가받고, 그 memory의 기준 주소를 void* 형으로 반환 받는다. 


이후 주소의 형식을 변경하고 (int*든 char*든) pointer 변수에 넣어 사용하면 된다. 


접근 및 사용방식은 배열과 동일하다. 


사용 후 free() 함수를 사용해 주소를 반환해야 한다. 





malloc()한 공간 앞뒤 memory는 fd 4개로 채워지는데 이 fd가 변경되면 buffer overflow를 탐지하고 free() 할 때 경고하게 된다. 

(fd를 넘어서 변경해도 탐지한다.)



변수를 선언하면 0으로 초기화 하듯, 메모리도 할당받으면 0으로 초기화하는 것이 좋은데


이때는 memset() 이나 calloc()을 사용하면 된다. 


동적 할당한 메모리의 크기를 알고 싶은 경우 

windows - _msize() 

UNIX - malloc_usable_size()  함수를 사용하면 된다. 



메모리 복사


지금까지는 내용을 복사하기 위해서 단순 대입 연산자를 썼는데, 배열에서는 불가능하다. 



szSrcBuf, szDesBuf 모두 메모리의 주소 즉 상수이므로 대입이 불가능하다. 


이럴 땐 memcpy나 strcpy를 사용한다. 



복사

shallow copy - 주소만 복사 


Deep copy - 내용만 복사 



pszNewData를 출력하면 정상적으로 hello가 나오지만 free()를 할 때 에러가 발생한다. 


발생 이유 


16번 라인에서 pszNewData에 동적할당한 메모리의 주소를 저장했다. 

17번 라인에서 pszNewData에 szDesBuf의 주소를 넣었다. 

20번 라인에서 puts를 사용해서 pszNewData를 출력했기에 szDesBuf에 저장된 "Hello"가 출력된다.

22번 라인에서 free()를 사용해 pszNewData에 저장된 주소의 메모리를 할당 해제 하려고 하지만 그 메모리는 16번째 라인에서 할당한 Heap 영역의 메모리가 아니라 스택 영역에 있는 szDesBuf의 메모리 주소이기에 에러가 발생한다. 


- 만일 free()를 사용하지 않는다면 memory leak은 발생하고, 에러는 발생하지 않아 heap 메모리를 반납하지 않고 계속 프로그램을 실행하게 되므로 큰 프로그램의 경우 문제가 될 수 있다. 



메모리 비교 


메모리 복사와 같은 이유로 단순 비교 연산을 사용하면 안된다. 


memcmp(), strcmp() 함수를 사용한다. 



문자열 검색


검색 대상의 문자열에서 원하는 문자열이 존재하는지 확인하는 함수 


strstr() 함수를 사용한다. 


strstr() 을 사용해 나온 주소값 - 검색 대상 문자열 = 해당 문자의 인덱스번호 



realloc() - 이미 할당된 메모리를 재할당하는 함수 


sprintf() - 문자열을 특정 주소의 메모리에 출력하는 함수 형식문자열을 조합할 수 있다는 장점이 있다. 






- 출처 : 독하게 시작하는 C 프로그래밍 (최호성, 루비 페이퍼)