C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[75208] Re:릴리즈 이후 문제발생에 대해 질문드립니다.
빌더(TWx) [builder] 2944 읽음    2018-12-12 13:15
HSH 님이 쓰신 글 :
: 왕초보 개발자입니다.
: 현재 릴리즈 한 프로그램에서 access Violation이 자꾸 발생합니다.
:
: 오류 내용은 Access violation at address 0059c5e4 in module 'A.exe' read of address 00000012 입니다.
:
: 오류가 나는 위치를 포럼 내에서 검색해서 계산해 봤지만 map파일에서 오류를 확인 할 수가 없습니다..
: 어떤 방식으로 해결해야할까요?
:
: 사용되는 함수가 fnsplit, FileExists, LoadFromCSV, ExtractFileDir 인데 이 중에서 오류가 날 가능성이 있을까요?
:
: ps. 외부 프로그램이 엑셀정도만 깔려있는 컴퓨터 입니다.
: ps2. 사용환경은 6.0 버전, win7 32비트입니다.
: ps3. 현재 제가 보유중인 노트북 (win 10 64비트에서는 잘 돌아가며, win7 32비트에서도 잘 돌아가는 프로그램입니다.)




답변:



map 파일이 첨부되어 있지도 않고 본문에 언급되어 있는 정도로는 확정할 수 있는 내용이 하나도 없습니다.
access violation이 발생하는 해당 PC에서 직접 디버깅 해보는 게 가장 빠른 방법이고.



1.

rad 10.3 기준으로 설명하면 프로젝트 map 파일 옵션에서 'Detailed segment' 선택하면
링커가 다음과 같은 형식으로 map 파일을 생성하는데...



Start Length Name Class
0001:00401000 000318F6CH _TEXT                  CODE
0002:0071A000 00000DEA8H _DATA                  DATA
0003:00727EA8 00000EB90H _BSS                   BSS
0004:00000000 0000000C0H _TLS                   TLS
.........

0001:00013A88  __fastcall System::initialization()
0001:000039A8  __fastcall TForm1::Button1Click(System::TObject *)
0001:00003060  __fastcall TForm1::TForm1(System::Classes::TComponent *)
0001:00003A0C  __fastcall TForm1::~TForm1()


'0001:000039A8  __fastcall TForm1::Button1Click(System::TObject *)' 을 예로 들면
앞부분 세그먼트 인덱스가 1이고 세그먼트 Relative 옵셋이 000039A8 이죠.


그리고 윗부분의 세그먼트 정보에서 보면

0001:00401000 000318F6CH _TEXT                  CODE

세그먼트 1의 image base가 적용된 rva 시작 주소는 00401000 입니다.

따라서 '0001:000039A8  __fastcall TForm1::Button1Click(System::TObject *)' 을 image base가 적용된
rva 값으로 변환 하려면 000039A8 옵셋 값에  00401000을 더해야 합니다.
더하면 4049A8 이 되고, 이 값이 rva 값 입니다.

.exe 바이너리 파일에서 rva 4049A8 인 TForm1::Button1Click(System::TObject *) 에 해당하는 위치는
exe 헤더 section 테이블을 참조해서 해당 섹션의 physical disk offset 값을 찾아서
rva 값에서 00401000을 뺀 relative 값을 역산해서 해당 위치를 알아내면 됩니다.

0001:00013A88  __fastcall System::initialization()
0001:000039A8  __fastcall TForm1::Button1Click(System::TObject *)
0001:00003060  __fastcall TForm1::TForm1(System::Classes::TComponent *)
0001:00003A0C  __fastcall TForm1::~TForm1()

각기 심볼에 대해서 rva 값을 구해서...
rva 값과 심볼네임을 이용해서 심볼 테이블을 생성해서 rva 값 순서대로 sort 하세요.
링커가 생성하는 map 파일은 sort가 되어있지 않습니다.

이렇게 map 파일 심볼테이블을 생성해 놓으면...
Sort 되어 있는 심볼엔트리를 이용해서 예외가 발생한 주소에 해당하는
심볼네임 + offset 위치를 바로 추정할 수 있게 됩니다.

이게 map 파일을 이용하는 방법이고...




2.

rva 주소에 대한 해당 소소코드의 라인넘버를 알아낼 수도 있는데
이건 컴파일러가 생성하는 디버깅 포맷을 직접 이용해야 합니다.

Jedi 라이브러리에 TD32 디버깅 포맷을 정의해 놓은 유닛이 있으니
그걸 이용해도 되고요.


EurekaLog 같은 툴을 돈 들여서 살 필요도 없지요. 다 이런 식으로 구현해 놓은 것에 불과한 겁니다.

Visual Studio 처럼 dbghelp api 형식으로 오픈 해 놓으면 디버깅 정보, call stack frame 정보를 간단하게 처리할 수 있는 건데
엠바에선 오픈해 놓고 있는게 하나도 없지요. 얘들이 왜 이렇게 폐쇄적인 건지.

+ -

관련 글 리스트
75205 릴리즈 이후 문제발생에 대해 질문드립니다. HSH 2696 2018/12/11
75208     Re:릴리즈 이후 문제발생에 대해 질문드립니다. 빌더(TWx) 2944 2018/12/12
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.