게시판 즐겨찾기
편집
드래그 앤 드롭으로
즐겨찾기 아이콘 위치 수정이 가능합니다.
뻘글] 몇날며칠을 고생한 메모리 누수를 잡았습니다!
게시물ID : programmer_12017짧은주소 복사하기
작성자 : 물어라이코스
추천 : 13
조회수 : 5685회
댓글수 : 21개
등록시간 : 2015/07/10 17:16:30
으헝헝헝헝헝 ㅠㅠㅠㅠㅠㅠ
정말 프게에서 많은 도움을 받았습니다. ㅠㅠㅠㅠㅠ
글이 워낙 여러개이고 뒤로 밀린터라...
결과 보고는 드려야 할 것 같아서요....

1. 프로그램의 목적
 - HTTP를 통해 제공되는 JSON 데이터를 가져와서 가공후 DB에 저장한다.

2. 여러가지 사항들
 - 구동 환경은 centos
 - 컴파일러는 gcc
 - C 언어
 - mysql
 - 반복 작업을 무한히 해야하며 빠를 수록 좋지만 상한선은 1초당 20회. (json 데이터 제공측 제한)

3. 사용된 라이브러리
 - curl (http://curl.haxx.se/)
 - json-c (https://linuxprograms.wordpress.com/2010/05/20/json-c-libjson-tutorial/)
 - mysql

4. 프로그램 구동 순서
1) curl을 이용하여 웹 데이터를 가져온다.
2) 가져온 데이터를 json object로 만든다.
3) 데이터를 처리한다.
4) db에 입력한다.


5. 대략적인 코드 구성
main(){
변수 선언

for{
curl에서 데이터 가져옮
json object로 만듦
데이터 처리
(일부)
for{
데이터 처리
db 입력
}
db 입력
}

mysql_close()
}

--> 함수 없음. 그냥 main에서 통짜로 실행


6. 문제 발생
- 1차 메모리 누수 ( 반복문 1건당 메모리 사용량 0.5%씩 상승 )
멍청하게도 모든 변수에 대해 메모리 반환을 하지 않음으로 발생.
동적 할당으로 선언했던 변수들을 free 로 반환.


- 2차 메모리 누수 ( 반복문 1건당 메모리 사용량 0.4%씩 상승 )
그럼에도 불구하고 메모리 누수가 발생함.
동적할당 했던 변수들을 전부 없애고 고정으로 변경.
추가로 찾아보니
json object 로 선언된 변수들을 초기화(?) 해주는 함수를 써줘야 한다고 함.
전체 for문 하단에 다음과 같이 추가

if (!jobj){ json_object_put(jobj); }


- 3차 메모리 누수 ( 반복문 100건당 메모리 사용량 0.1%씩 상승 )
그럼에도 불구하고 매번 반복문이 반복될때마다 계속해서 메모리 누수 발생.
찾아보니 curl에도 메모리 누수가 있다고 함.

curl_easy_cleanup(curl);
curl_global_cleanup();
free(resData.response); // url에서 가져온 데이터를 보관하는 변수. 데이터 크기에 따라 동적할당을 하므로 free로 반환해야함.


- 4차 메모리 누수 ( 반복문 100건당 메모리 사용량 0.1%씩 상승 )
아직도 ㅋㅋㅋㅋㅋㅋㅋㅋㅋ .. ㅋㅋㅋ.ㅋ.ㅋㅋㅋㅋㅋㅋㅋㅋ............
이때부터 혹시나 하는 마음에 mysql 관련 함수들에도 메모리 누수가 있나 확인해보았으나 없음.
오유에서 도움을 받아 valgrind 로 검사를 해보니, 여전히 curl 에서 문제가 있다고 나옴.

더 구글링 해봐도 정답이 없길래.....
게으름 부리지 말고 작업들을 함수로 따로 만들기로 함.
함수 작동이 끝나면 사용했던 메모리는 전부 반환하겠지 뭐! <-- 라는 생각..

char* get_json(char *url) {
인자로 넘어온 url에서 데이터를 가져오는 작업
}


- 5차 메모리 누수 ( 반복문 1000건당 메모리 사용량 0.1%씩 상승 )
ㅋㅋㅋ......
이때 오유에서 아예 고정 길이로 데이터를 받아버리라는 조언을 얻음.
그렇게 코드를 변경 했음에도 (char test[35000];) 여전히 메모리 누수가 발생함.


- 6차 메모리 누수 ( 반복문 1000건당 메모리 사용량 0.1%씩 상승 )
차근차근 다시 생각을 해봤는데, 아주 중요한 문제가 있었음.
새롭게 만든 get_json() 함수에서... 이런 멍청한 부분이 있음.

char* get_json(){
데이터 처리
data = malloc(siezeof(char)*size);
return data;
}

!?

그렇다고 free(data)를 한 후 return data; 를 할수는 없었기에 머리가 아파짐.

ㅁㄴ이ㅏ러니ㅏㅇ러니아러미낭러민아럼ㄴ이라ㅓㅁ닝러

어떻게 해야할까...........

생각하다가...

한번도 안해본건데.... 왠지 될거 같다는 생각으로 이렇게 바꿈.


void get_json(char *url, char **data){
데이터 처리
*data = malloc(sizeof(char) * size+1);
strcpy(data, 처리된데이터);
return data;
}

void main(){
char *data;
get_json(url, &data);
jobj = json_tokener_parse(data); // json 으로 파싱
free(data);
}

-> 데이터를 리턴시킬 문자열 변수를 main에서 선언하고 그 주소를 인자로 넘긴 후,
get_json함수에서 데이터 길이에 따라 동적 할당을 해주고 데이터 복사 후 함수 종료.

-> 데이터가 리턴 되었으므로 json object를 만든 다음 바로 free로 메모리 반환.

7. 결과
프로그램 실행시 메모리 점유율 0.8%
10만건을 반복 후 메모리 점유율 0.8%



도움을 주신 오유 프게 분들께 감사드립니다. (__);
이제 이걸 멀티 쓰레드로 해보는걸 한번 도전해보려구요 ^-^ 아이고 좋다....
전체 추천리스트 보기
새로운 댓글이 없습니다.
새로운 댓글 확인하기
글쓰기
◀뒤로가기
PC버전
맨위로▲
공지 운영 자료창고 청소년보호