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

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[1096] [Exception] AccessViolation 메세지로 에러 위치 찾기
장성호 [nasilso] 36876 읽음    2012-06-20 20:35
음..
이번에도 간단한 팁입니다.
AccessViolation 에러 메세지의 주소에 대한 설명입니다.


[AccessViolation 에러 메세지]

AccessViolation 에러 메세지는 보통 다음과 같이 뜹니다.

"Access violation at address 00401BF6 in module 'Project4.exe'. Write of address 00000010"


위 메세지에는 2가지 addess가 나옵니다.


1. 첫번째 address는 문제가 되는 code(바이너리) 위치를 나타내고

2. 두번째 address는 access(read 또는 write) 하려는 메모리 주소를 나타냅니다.



[첫번째 Address로 에러코드 위치 찾기]

메세지의 첫번째 주소를 이용해서 문제가 되는 코드의 위치를 찾는 팁은 굉장히 많이 있습니다.
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=600
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=863
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=886
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=887

http://www.delmadang.com/community/bbs_view.asp?bbsNo=3&bbsCat=0&st=S&keyword=%uC561%uC138%uC2A4%uBC14%uC774%uC62C%uB894%uC774&indx=197109

위 팁들을 이용하면 많은 도움이 될것입니다.

[첫번째 주소로 찾은 코드에 전혀 문제가 없는 경우엔?]
그런데 첫번재 주소로 찾은 코드에 전혀 문제가 없는 경우가 많이 있습니다.

이미 어느 정도 검증된 모듈인 VCL내부에서도 AccessViolation이 날때 있구요


[두번째 주소를 이용해 에러 원인찾기 시도..]

첫번째 주소로 에러 원인을 찾지 못하거나..
혹은  에러원인을 찾기 전에 두번째 주소의 값을 보면 어느정도의 힌트를 얻을수 있습니다.


[에러 발생 코드 1]

"Access violation at address 00401BF6 in module 'Project4.exe'. Write of address 00000010"

위에 난 에러는 다음과 같은 코드에서 발생한 것입니다.

class TMyClass
{
public:
	int m_iData[4];
	int m_iWid;
	int m_iHei;

	void SetSize(int iWid,int iHei)
	{
		m_iWid=iWid;  // Access-Violation 발생 위치
		m_iHei=iHei;
	}
};
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TMyClass *mCls=NULL;
	try
	{
		mCls->SetSize(100,200); // 잘못된 코드 
	}
	catch(Exception &err)
	{
		ShowMessage(err.Message);
	}
}
//---------------------------------------------------------------------------


Write of address 가  "00000010"   즉  16번지에서 발생했습니다.

첫번째 주소로 에러 코드위치를 찾으면 TMyClass 의 SetSize 메소드에서 에러가 난것입니다.
하지만 SetSize메소드에는 별 문제가 없죠

원인은 Button1Click 함수에서 TMyClass의 NULL객체에 SetSize함수를 호출한것이죠



[에러 발생 코드 2]

에러가 발생한 class의 멤버변수인 m_iData 주석 처리하면 어떻게 될가요?
class TMyClass
{
public:
	// int m_iData[4]; // 다음과 같이  Data를 주석 처리하면?
	int m_iWid;
	int m_iHei;

	void SetSize(int iWid,int iHei)
	{
		m_iWid=iWid;  // Access-Violation 발생 위치
		m_iHei=iHei;
	}
};


다음과 같은 메세지가 발생합니다.


Write of address 가  "00000000"   즉  0 번지에서 발생했습니다.

[Write of Address는 ?]

즉 AccessViolation의
두번째 Address는
객체(클래스 또는 구조체)의 시작 주소에서 부터 Offset 위치의 메모리 주소입니다.


만약 Write of Address 가    0x20 이면  
객체의 시작부터 32번째 변수를 access하려다가 에러가 발생한 것입니다.


Class가 상속을 받거나 가상함수등이 있다면..
parent-class의 size 만큼 offset이 더 커질것입니다.


[두번째 address의 값이 작은 경우엔..]
위와같이 Write of Address의 값이 작은 경우엔..

대부분의 경우게 객체의 주소가 NULL이거나 쓰레기 값인 경우가 대부분입니다.


이경우엔 모듈 내부에서 원인을 아무리 찾아도 답이 없습니다.
첫번째 주소위치의 코드를 찾아도 원인을 찾지 못합니다.


그 모듈을 사용하는 달느 곳에 원인이 있으니까요


문론 다음과 같은 코드에서도 주소는 똑같이 0x10 , 16번지 에서 에러가 납니다.
void __fastcall TForm1::Button2Click(TObject *Sender)
{
	int *p=NULL;
	p[4]=100;  //Write of Address 00000010 
}
//---------------------------------------------------------------------------


이경우엔 첫번째 주소를 이용해 코드 위치를 찾아보면 에러 원인을 찾을수 있겠죠



[결론]

Access-Violation이 발생했을때 
첫번째 address뿐만 아니라  두번째 address의 주소값도  잘 보라는 것입니다.

에러 메세지를 볼때  주소가 모듈(dll 이나 bpl) 등에서 발생했더라도
모듈에 문제가 없는 경우가 매우 많이 있습니다.

모듈 사용을 잘못했는데..
모듈에서 백날 찾아봐야 답이 없죠

오늘도
제 직장동료가 accessviolation의 원인을
메세지 보고 모듈에서만 찾다가 시간을 엄청 낭비했었죠


...

[사족]

별 대단한 팁은 아닌데..
혹시나 누군가에게 도움이 될까하여 올려봅니다.


그럼..

+ -

관련 글 리스트
1096 [Exception] AccessViolation 메세지로 에러 위치 찾기 장성호 36876 2012/06/20
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.