[완료]코어덤프 문제입니다. 고수님들의 조언 꼭 부탁드립니다.
글쓴이: gennaio / 작성시간: 월, 2009/06/08 - 4:33오후
접수번호 하나를 받아서 파일 두개를 읽어서 간단하게 리포팅하는 서비스입니다.
거의 해결은 되었는데요. main()에서 ord_main()과 chg_main()을 호출하는 데요.
chg_main()을 호출하고선 이상하게 코어덤프가 떨어지네요.
참고로 ord_main()과 chg_main()은 거의 같은 함수이고, 다만 읽는 파일이 다를 뿐입니다.
ord_main()은 이상없이 통과하는데 chg_main()은 내부적으로 다돌고, main()으로 다시 리턴하면서
코어가 발생한 거 같은데요.. chg_main()에서 마지막 부분까진 찍었거든요. 근데 main()에서 리턴되고 나서
찍는 부분이 찍히지 않고 코어가 발생하네요. 정말 ㅜ.ㅡ
dbx로 코어 분석을 해볼려고 했는데, 전체 코어가 아니라면서, 코어분석도 제대로 안되구요.
고수님들이 어떤 부분에서 에러가 났는지에 대해서, 조언과 분석방법을 알려주시면 감사하겠습니다.
실행방법 ) log_report [접수번호]
dhkim:/usr># log_report 3
실행파일 뒤에 3번이 접수번호라는 건데요.. 두개 파일에서 이 접수번호를 찾아, 그 로그를 파싱해서 리포팅 하는
거랍니다.
부탁드립니다.
파일을 첨부하지 못하는 관계로 제 블로그로 이동하셔서 파일을 보시면 감사하겠습니다.
파일은 소스파일과 로그파일 2개입니다. 다시 한번 많은 분들이 관심가지셔서 조언 부탁드립니다.
/*[ header: 로그 리포트 name: log_report.c synopsis: return: 없음 인수 : char file (조회번호) description: FIX log Report remarks: 없음 table: date: 09.06.01 ]*/ #define LINE_SIZE 40 #define BUF_SIZE 256 #define C_JSNO_SIZE 9 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/time.h> /* #include "common.h" #include "siteinc.h" #include "fepst.h" #include "tradeframe.h"*/ /*extern DateTime_st TimeBuf;*/ /* common.c에서 선언 */ /* usa_chgrcv-USA1.log usa_ordsnd-USA1.log*/ /* 주문로그 리포트 구조체 */ typedef struct OrderReportSts { char order_time [14+1]; /* 주문시간 */ char svr_name [14+1]; /* 서버명 */ char ord_type [ 1+1]; /* 주문형태 */ char currency [ 3+1]; /* 통화 */ char security_id[15+1]; /* 종목코드 */ char price [15+1]; /* 단가 */ char order_qty [15+1]; /* 주문수량 */ } OrderReportSts_sts; /* 체결로그 리포트 구조체 */ typedef struct ChgReportSts { char chg_time [14+1]; /* 체결시간 */ char svr_name [14+1]; /* 서버명 */ char ord_status [ 1+1]; /* 주문상태 */ char ord_type [ 1+1]; /* 주문형태 */ char currency [ 3+1]; /* 통화 */ char security_id [15+1]; /* 종목코드 */ char price [15+1]; /* 단가 */ char avg_px [15+1]; /* 평균단가 */ char order_qty [15+1]; /* 주문수량 */ char cum_qty [15+1]; /* 체결수량 */ char leaves_qty [15+1]; /* 미체결수량 */ } ChgReportSts_sts; /* 접수번호 가져오기 */ int getJsno(char* buf) { char c_jsno[C_JSNO_SIZE+1]; long l_jsno = 0; int j; memset(c_jsno, 0x00, sizeof(c_jsno)); if (!strncmp(buf, "ClOrdID(11)", strlen("ClOrdID(11)"))) { j = 0; /* 로우 끝까지 추적 */ while (buf[j] != '\0') { /* printf("[%d] %c\n", j, buf[0]); */ /* 로우 끝이면 break */ if (buf[j] == '\0') break; if (!strncmp(&buf[j], ":", 1)) { /* ClOrdID(11) 열에서 ':'를 찾으면, 그 포인터를 저장 */ strncpy(c_jsno, &buf[j]+1, C_JSNO_SIZE); } j++; } } return atol(c_jsno); } /* 주문로그 리포트 프린트 */ void print_ord_report(char data[][BUF_SIZE], int jsno) { int i = 0; OrderReportSts_sts __ord; OrderReportSts_sts *ord_p = &__ord; bzero(ord_p, sizeof(OrderReportSts_sts)); #if 0 while (1) { printf(" [%d] data[%s]\n", i, data[i]); /* CompressFlag(F69)가 전문의 마지막이므로 여기서 Break */ if (!strncmp(data[i], "CompressFlag(F69)", strlen("CompressFlag(F69)"))) break; i++; } #endif strncpy(ord_p->order_time , data[0] + 1 , strlen("05/29 21:24:21")); strncpy(ord_p->svr_name , data[6] + 40, strlen("usa_ordsndUSA1")); strncpy(ord_p->ord_type , data[13] + 34, strlen("2")); strncpy(ord_p->currency , data[19] + 34, strlen("USD")); strncpy(ord_p->security_id , data[15] + 34, sizeof(ord_p->security_id)-1); strncpy(ord_p->price , data[14] + 34, sizeof(ord_p->price )-1); strncpy(ord_p->order_qty , data[23] + 34, sizeof(ord_p->order_qty )-1); printf("\n\n"); printf(" **********************************************\n"); printf(" 주문로그 Report \n"); printf(" **********************************************\n"); printf(" 접수번호 : [%d] \n", jsno ); printf(" 주문시간 : [%s] \n", ord_p->order_time ); printf(" 서버명 : [%s] \n", ord_p->svr_name ); printf(" 주문형태 : [%s] \n", ord_p->ord_type ); printf(" 통화 : [%s] \n", ord_p->currency ); printf(" 종목코드 : [%s] \n", ord_p->security_id); printf(" 단가 : [%s] \n", ord_p->price ); printf(" 주문수량 : [%s] \n", ord_p->order_qty ); } /* 체결로그 리포트 프린트 */ int print_chg_report(char data[][BUF_SIZE], int jsno) { int i = 0; ChgReportSts_sts __chg; ChgReportSts_sts *chg_p = &__chg; bzero(chg_p, sizeof(ChgReportSts_sts)); #if 1 strncpy(chg_p->chg_time , data[0] + 1, strlen("05/29 21:24:21")); /* 체결시간 */ /*strncpy(chg_p->svr_name , data[ ] + 40, sizoef(chg_p->svr_name )-1);*/ /* 서버명 */ strncpy(chg_p->ord_status , data[28] + 34, sizeof(chg_p->ord_status )-1); /* 주문상태 */ strncpy(chg_p->ord_type , data[29] + 34, sizeof(chg_p->ord_type )-1); /* 주문형태 */ strncpy(chg_p->currency , data[21] + 34, sizeof(chg_p->currency )-1); /* 통화 */ strncpy(chg_p->security_id , data[31] + 34, sizeof(chg_p->security_id )-1); /* 종목코드 */ strncpy(chg_p->price , data[30] + 34, sizeof(chg_p->price )-1); /* 단가 */ strncpy(chg_p->avg_px , data[18] + 34, sizeof(chg_p->avg_px )-1); /* 평균단가 */ strncpy(chg_p->order_qty , data[27] + 34, sizeof(chg_p->order_qty )-1); /* 주문수량 */ strncpy(chg_p->cum_qty , data[20] + 34, sizeof(chg_p->cum_qty )-1); /* 체결수량 */ strncpy(chg_p->leaves_qty , data[36] + 34, sizeof(chg_p->leaves_qty )-1); /* 미체결수량 */ printf("\n\n"); printf(" **********************************************\n"); printf(" 체결로그 Report \n"); printf(" **********************************************\n"); printf(" 접수번호 : [%d] \n", jsno ); printf(" 체결시간 : [%s] \n", chg_p->chg_time ); printf(" 서버명 : [%s] \n", chg_p->svr_name ); printf(" 주문상태 : [%s] \n", chg_p->ord_status ); printf(" 주문형태 : [%s] \n", chg_p->ord_type ); printf(" 통화 : [%s] \n", chg_p->currency ); printf(" 종목코드 : [%s] \n", chg_p->security_id ); printf(" 단가 : [%s] \n", chg_p->price ); printf(" 평균단가 : [%s] \n", chg_p->avg_px ); printf(" 주문수량 : [%s] \n", chg_p->order_qty ); printf(" 체결수량 : [%s] \n", chg_p->cum_qty ); printf(" 미체결수량 : [%s] \n", chg_p->leaves_qty ); #endif printf("11\n"); return 0; } /* 주문메인 */ void ord_main(int argc, char **argv) { FILE *fp = NULL; /* 전문 한줄 버퍼 */ char buf[BUF_SIZE]; /* 접수번호 */ long gl_jsno = 0; /* 접수번호에 찾으면 true */ int found_flag = FALSE; /* 접수번호에 해당되는 데이터를 담는 버퍼 */ char data[LINE_SIZE][BUF_SIZE]; /* for loop */ int i, k, l; /* 초기화 */ memset(buf , 0x00, sizeof(buf)); /* 접수번호에 해당되는 전문이 쌓이는 공간 초기화 */ for(k = 0; k < LINE_SIZE; k++) { memset(data[k], 0x00, BUF_SIZE); } /* 접수번호 출력 */ printf("\n입력된 주문로그 접수번호 [%s]\n", argv[1]); /* 스트림 OPEN */ /* fp = fopen(argv[1], "rt"); */ fp = fopen("./usa_ordsnd-USA1.log", "rt"); if (fp == NULL) { perror("file open error 1 : "); exit(0); } /* 스트림 한줄씩 read */ while (!feof(fp)) { /* printf("fp[%p]\n", fp); */ /* 파일포인터가 널이면 브레이크 */ if (fgets(buf, BUF_SIZE, fp) == NULL) { /* 찾지 못했으면, 에러 */ if (found_flag == FALSE) { printf("입력된 주문로그 접수번호에 해당되는 전문이 없습니다.\n"); } break; } /* 데이터만 복사 - 이전 자료는 깨끗이 지우고 다시 세팅*/ memset(data[i], 0x00, BUF_SIZE); strncpy(data[i], buf, strlen(buf)-1); /* printf("[%d]data[%s]\n", i, data[i]); */ /* 접수번호 가져오기 */ if (!strncmp(buf, "ClOrdID(11)", strlen("ClOrdID(11)"))) { /* if (getJsno(buf) != 0) { */ gl_jsno = getJsno(buf); } /* 데이터가 시작하면 i를 0으로 세팅 */ if (strncmp(buf + 25, "FML", strlen("FML")) == 0) { i = 0; /* 접수번호를 찾았을 경우는 브레이크 */ if (found_flag == TRUE) break; } /* 접수번호가 같은 데이터만 복사 */ if (gl_jsno == atoi(argv[1])) { found_flag = TRUE; } /* 다음 로우를 읽기 위해 리셋 */ memset(buf, 0x00, BUF_SIZE); i++; } /* 주문로그 출력 */ if (found_flag == TRUE) print_ord_report(&data[0], gl_jsno); /* 파일포인터 닫기 */ fclose(fp); } /* 체결메인 */ int chg_main(int argc, char **argv) { FILE *fp1 = NULL; /* 전문 한줄 버퍼 */ char buf[BUF_SIZE]; /* 접수번호 */ long gl_jsno = 0; /* 접수번호에 찾으면 true */ int found_flag = FALSE; /* 접수번호에 해당되는 데이터를 담는 버퍼 */ char data[LINE_SIZE][BUF_SIZE]; /* for loop */ int i, k, l; /* 초기화 */ memset(buf , 0x00, sizeof(buf)); /* 접수번호에 해당되는 전문이 쌓이는 공간 초기화 */ for(k = 0; k < LINE_SIZE; k++) { memset(data[k], 0x00, BUF_SIZE); } /* 접수번호 출력 */ printf("\n입력된 체결로그 접수번호 [%s]\n", argv[1]); /* 스트림 OPEN */ /* fp1 = fopen(argv[1], "rt"); */ fp1 = fopen("./usa_chgrcv-USA1.log", "rt"); if (fp1 == NULL) { perror("file open error 1 : "); exit(0); } /* 스트림 한줄씩 read */ while (!feof(fp1)) { /* printf("fp1[%p]\n", fp1); */ /* 파일포인터가 널이면 브레이크 */ if (fgets(buf, BUF_SIZE, fp1) == NULL) { /* 찾지 못했으면, 에러 */ if (found_flag == FALSE) { printf("입력된 체결로그 접수번호에 해당되는 전문이 없습니다.\n"); } break; } /* 데이터만 복사 - 이전 자료는 깨끗이 지우고 다시 세팅*/ memset(data[i], 0x00, BUF_SIZE); strncpy(data[i], buf, strlen(buf)-1); /* printf("[%d]data[%s]\n", i, data[i]); */ /* 접수번호 가져오기 */ if (!strncmp(buf, "ClOrdID(11)", strlen("ClOrdID(11)"))) { gl_jsno = getJsno(buf); } /* 데이터가 시작하면 i를 0으로 세팅 */ if (strncmp(buf + 25, "FML", strlen("FML")) == 0) { i = 0; /* 접수번호를 찾았을 경우는 브레이크 */ if (found_flag == TRUE) break; } /* 접수번호가 같은 데이터만 복사 */ if (gl_jsno == atoi(argv[1])) { found_flag = TRUE; } /* 다음 로우를 읽기 위해 리셋 */ memset(buf, 0x00, BUF_SIZE); i++; } /* 체결로그 출력 */ if (found_flag == TRUE) { int rtn = 0; rtn = print_chg_report(&data[0], gl_jsno); printf("33\n"); } printf("44\n"); /* 파일포인터 닫기 */ fclose(fp1); printf("55\n"); return 0; } int main(int argc, char **argv) { int rtn = 0; ord_main(argc, argv); rtn = chg_main(argc, argv); printf("체결로그 성공[%d]\n", rtn); /* printf("22\n"); */ return 0; }
Forums:
초기화 부분이
초기화 부분이 누락된 부분을 다시 한번 확인해보시기 바랍니다...
처음에 코딩을 시작할때에 놓치기 쉬운 부분이지만.. 방어적 코딩을 하는 습관을 가지시길 바라겠습니다..
valgrind 결과입니다.
일단 디버깅에 대한 기본적인 내용을 숙지하시는 게 좋을 것 같네요.
$gdb --args ./a.out 3
으로 실행하셔도 트레이스 가능하실테고요.
아래는 valgrind 실행결과 입니다. 초기화 문제가 맞는듯 합니다.
$ valgrind --leak-check=full --leak-resolution=high ./a.out 3
==2075== Memcheck, a memory error detector.
==2075== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==2075== Using LibVEX rev 1854, a library for dynamic binary translation.
==2075== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==2075== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation framework.
==2075== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==2075== For more details, rerun with: -v
==2075==
입력된 주문로그 접수번호 [3]
==2075== Use of uninitialised value of size 4
==2075== at 0x4027368: memset (mc_replace_strmem.c:493)
==2075== by 0x8048EE4: ord_main (log_report-gennaio80.c:244)
==2075== by 0x804933E: main (log_report-gennaio80.c:402)
==2075==
==2075== Use of uninitialised value of size 4
==2075== at 0x402737C: memset (mc_replace_strmem.c:493)
==2075== by 0x8048EE4: ord_main (log_report-gennaio80.c:244)
==2075== by 0x804933E: main (log_report-gennaio80.c:402)
==2075==
==2075== Use of uninitialised value of size 4
==2075== at 0x40265A3: strncpy (mc_replace_strmem.c:291)
==2075== by 0x8048F1C: ord_main (log_report-gennaio80.c:245)
==2075== by 0x804933E: main (log_report-gennaio80.c:402)
==2075==
==2075== Conditional jump or move depends on uninitialised value(s)
==2075== at 0x40265C5: strncpy (mc_replace_strmem.c:77)
==2075== by 0x8048F1C: ord_main (log_report-gennaio80.c:245)
==2075== by 0x804933E: main (log_report-gennaio80.c:402)
==2075==
==2075== Conditional jump or move depends on uninitialised value(s)
==2075== at 0x4026668: strncpy (mc_replace_strmem.c:80)
==2075== by 0x8048F1C: ord_main (log_report-gennaio80.c:245)
==2075== by 0x804933E: main (log_report-gennaio80.c:402)
==2075==
==2075== Conditional jump or move depends on uninitialised value(s)
==2075== at 0x40265E3: strncpy (mc_replace_strmem.c:291)
==2075== by 0x8048F1C: ord_main (log_report-gennaio80.c:245)
==2075== by 0x804933E: main (log_report-gennaio80.c:402)
입력된 체결로그 접수번호 [3]
==2075==
==2075== Use of uninitialised value of size 4
==2075== at 0x4027368: memset (mc_replace_strmem.c:493)
==2075== by 0x8049191: chg_main (log_report-gennaio80.c:346)
==2075== by 0x804934F: main (log_report-gennaio80.c:404)
==2075==
==2075== Use of uninitialised value of size 4
==2075== at 0x402737C: memset (mc_replace_strmem.c:493)
==2075== by 0x8049191: chg_main (log_report-gennaio80.c:346)
==2075== by 0x804934F: main (log_report-gennaio80.c:404)
==2075==
==2075== Use of uninitialised value of size 4
==2075== at 0x40265A3: strncpy (mc_replace_strmem.c:291)
==2075== by 0x80491C9: chg_main (log_report-gennaio80.c:347)
==2075== by 0x804934F: main (log_report-gennaio80.c:404)
==2075==
==2075== Conditional jump or move depends on uninitialised value(s)
==2075== at 0x40265C5: strncpy (mc_replace_strmem.c:77)
==2075== by 0x80491C9: chg_main (log_report-gennaio80.c:347)
==2075== by 0x804934F: main (log_report-gennaio80.c:404)
==2075==
==2075== Conditional jump or move depends on uninitialised value(s)
==2075== at 0x4026668: strncpy (mc_replace_strmem.c:80)
==2075== by 0x80491C9: chg_main (log_report-gennaio80.c:347)
==2075== by 0x804934F: main (log_report-gennaio80.c:404)
==2075==
==2075== Conditional jump or move depends on uninitialised value(s)
==2075== at 0x40265E3: strncpy (mc_replace_strmem.c:291)
==2075== by 0x80491C9: chg_main (log_report-gennaio80.c:347)
==2075== by 0x804934F: main (log_report-gennaio80.c:404)
==2075==
==2075== Invalid write of size 1
==2075== at 0x402663D: strncpy (mc_replace_strmem.c:291)
==2075== by 0x80491C9: chg_main (log_report-gennaio80.c:347)
==2075== Address 0xbe8dd000 is not stack'd, malloc'd or (recently) free'd
==2075==
==2075== Process terminating with default action of signal 11 (SIGSEGV)
==2075== Access not within mapped region at address 0xBE8DD000
==2075== at 0x402663D: strncpy (mc_replace_strmem.c:291)
==2075== by 0x80491C9: chg_main (log_report-gennaio80.c:347)
==2075==
==2075== ERROR SUMMARY: 749 errors from 13 contexts (suppressed: 11 from 1)
==2075== malloc/free: in use at exit: 352 bytes in 1 blocks.
==2075== malloc/free: 2 allocs, 1 frees, 704 bytes allocated.
==2075== For counts of detected errors, rerun with: -v
==2075== searching for pointers to 1 not-freed blocks.
==2075== checked 67,036 bytes.
==2075==
==2075== LEAK SUMMARY:
==2075== definitely lost: 0 bytes in 0 blocks.
==2075== possibly lost: 0 bytes in 0 blocks.
==2075== still reachable: 352 bytes in 1 blocks.
==2075== suppressed: 0 bytes in 0 blocks.
==2075== Reachable blocks (those to which a pointer was found) are not shown.
==2075== To see them, rerun with: --leak-check=full --show-reachable=yes
Segmentation fault
해결 ^^v 고수님들의 답변 진심으로 감사합니다.
배열 사이즈를 전문길이에 딱 맞게 잡은게 그랬네요.. 체결로그 전문의 한 단위가 40줄인데, 루프돌면서, 다른포인터로 찾아들어가
argc, argv 포인터가 깨졌더라구요. 그래서 라인사이즈를 50으로 늘려서 해주니 간단히 해결되었네요.
초기화 얘기를 언급해주셔서, 다시 찾았는데 역시나 그랬네요.
직접 돌려주시기 까지 해주시다니.. 물밑듯한 감동이 ㅜ.ㅡ
감사합니다.
valgrind의 결과도 그렇고 배열 크기 문제보다는...
지역 변수 i의 초기값이 정해져 있지 않습니다.
지역 변수 i를 초기화하는 것이 문제의 해결책이 될 듯 합니다.
댓글 달기