강좌 & 팁
메모리를 할당 받고 다시 반환 하는 과정에서 " .. free(): invalid pointer: .." 에러가 발생 했다면, 할당 받은
포인터변수의 주소를 변경해놓고 변경한 주소에서 그대로 free 를 시도한 경우 입니다.
간단히 예를 들어보면.
#include <stdio.h> #include <string.h> #include <stdlib.h> #define SIZE_BYTE 10 int main( void) { int i; char *buff;
buff = (char *)malloc( SIZE_BYTE); (char *)memset(buff,'a',SIZE_BYTE);
for(i=0;i<SIZE_BYTE;i++) { printf("buf[0] = %c\n",*(buff)); buff ++; } free( buff);
return 0; } |
위 코드를 실행해 보면 아래와 같은 메시지가 발생 합니다.
root@fa-vus:/staff/test# ./a buf[0] = a buf[1] = a buf[2] = a buf[3] = a buf[4] = a buf[5] = a buf[6] = a buf[7] = a buf[8] = a buf[9] = a *** glibc detected *** ./a: free(): invalid pointer: 0x08cb4012 *** ======= Backtrace: ========= /lib/i386-linux-gnu/libc.so.6(+0x73e42)[0xbede42] ./a[0x80484be] /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb934d3] ./a[0x80483b1] ======= Memory map: ======== 0045a000-00476000 r-xp 00000000 08:01 2229172 /lib/i386-linux-gnu/libgcc_s.so.1 ~ 생략 ~ |
사실 buff 내용을 출력 하기 위해 저런 식으로는 사용 하는 일이 없겠으나, 만약 위와 같이 buff 의 주소를
증가 했다면, for 문이 완료된 시점에서 buff 는 처음 malloc 으로 할당 받은 메모리의 시작 주소를 가르키지
않게 됩니다.
그런데 이상태에서 메모리를 반환 하고자 하면, 할당되지 않은 영역을 반환 하려는 꼴이 되는 것이지요.
해결 방법은 결국 free() 함수를 사용하기전 buff 의 주소를 할당 받았을 때의 원래 주소로 되돌리면 됩니다.
정확한 방법은 buff 의 주소를 직접 수정하지 않는 방법이겠지요.
하지만 어쩔 수 없이 변경해야 하는 상황이라면, 미리 주소를 저장해 둔 후 복귀 시키면 됩니다.
#include <stdio.h> #include <string.h> #include <stdlib.h> #define SIZE_BYTE 10 int main( void) { int i; char *buff; char *tmp;
buff = (char *)malloc( SIZE_BYTE); tmp = buff; (char *)memset(buff,'a',SIZE_BYTE);
for(i=0;i<SIZE_BYTE;i++) { printf("buf[%d] = %c\n",i,*(buff)); buff ++; }
buff =tmp; free( buff);
return 0; } |
코드를 보면, 처음 malloc 으로 할당받은 buff 의 시작 주소를 tmp 에 저장해 두었다가
나중에 메모리를 해제 하기 직전에 원래대로 복귀시키게 한 형태 입니다.
결과는 .
root@fa-vus:/staff/test# ./a buf[0] = a buf[1] = a buf[2] = a buf[3] = a buf[4] = a buf[5] = a buf[6] = a buf[7] = a buf[8] = a buf[9] = a root@fa-vus:/staff/test# |
네. 정상작으로 종료 되었군요.