[iOS / mac OS] 프로그램 이 obbc 에 붕 괴 됩 니 다.msgSend (), 어 떡 하지?

프로그램 붕 괴 는 obbcmsgSend (), 어 떡 하지?
 
가장 가능 한 이 유 는 풀 려 난 대상 에 게 메 시 지 를 보 내 거나 포인터 가 정확 하지만 다른 대상 에 의 해 내용 (예 를 들 어 메모리 크로스 오 버) 을 파괴 하거나 서 스 펜 션 포인 터 를 사용 하기 때 문 입 니 다.(dangling pointer). 가끔 은 메모리 오류 로 인해 실 행 될 때의 데이터 구조 가 파괴 되 기도 하지만, 일반적으로 문 제 는 수신 자 자체 에 있 습 니 다.
 
Debugger 를 사용 하 든 충돌 로그 (crash log) 를 통 해 backtrace (스 택 호출) 보다 훨씬 많은 정 보 를 얻 을 수 있 습 니 다.
 
 
수신 자 와 selector 레지스터 (Receiver and selector registers)
 
obsc msgSend () 는 CPU 레지스터 에 수신 자 대상 과 selector 를 저장 합 니 다. 이 값 들 은 문 제 를 분석 하 는 데 도움 을 줄 수 있 습 니 다.
 
구조 에 따라 사용 되 는 레지스터 가 다 를 수 있 습 니 다. 다음 표 는 Mac OS X Leopard (Snow Leopard 도 같 아야 합 니 다) 입 니 다.
  objc_msgSend objc_msgSend_fpret objc_msgSend_stret
  receiver SEL receiver SEL
i386
eax*
ecx
eax*
ecx
x86_64
rdi
rsi
rsi
rdx
ppc
r3
r4
r4
r5
ppc64
r3
r4
r4
r5
arm
r0
r1
r1
r2
* i386 의 설명: 수신 자 대상 은 대부분의 충돌 에서 eax 에 존재 합 니 다. 호출 경로 가 너무 길 면 eax 는 다른 값 으로 저장 할 수 있 습 니 다.
수신 자 와 불법 주소 해독 (Interpreting the receiver and invalid address)
 
수신 자 주소 와 불법 주 소 를 사용 하여 충돌 상황 을 만 들 수 있 습 니 다. 충돌 로그 에서 수신 자 주 소 는 위 표 에 열 거 된 레지스터 를 사용 하여 Thread State 에 저장 하고 불법 주 소 는 로그 맨 위 에 있 습 니 다.(보통 KERN PROTECTION FAILURE at 와 같이 표 시 됩 니 다. Debugger 콘 솔 에서 불법 주 소 는 프로그램 이 중 단 될 때 출력 되 며, 이 때 는 위 표 에 열 거 된 레지스터 를 사용 하여 수신 자의 주 소 를 출력 할 수 있 습 니 다.
    Program received signal EXC_BAD_ACCESS, Could not access memory.     Reason: KERN_PROTECTION_FAILURE at address: 0x00000001     0x00090ec4 in objc_msgSend ()     (gdb) p/x $eax     $1 = 0x1
이 테스트 프로그램 은 [(id) 1 release] 에 붕 괴 됩 니 다.
보통 두 가지 상황 중 하나 가 발생 합 니 다. 수신 자의 주 소 는 잘못 되 었 습 니 다. (이때 불법 주소 도 똑 같 거나 16 또는 32 바이트) 또는 수신 자의 주 소 는 합 리 적 이 고 불법 주 소 는 수신 자의 isa 지침 입 니 다. 후 자 는 일반적으로 풀 려 난 대상 을 사용 하려 고 시도 하기 때 문 입 니 다.
 
이 값 들 을 맞 춤 형 으로 찾 아야 할 뿐만 아니 라 근처에 있 는 값 도 찾 아야 합 니 다. 일부 구조 에서 불법 isa 는 isa + 16 또는 isa + 32 위치 에 프로그램 이 붕 괴 될 수 있 습 니 다.
 
정렬 되 지 않 으 면 16 으로 나 눌 수 없습니다 (Not divisble by 16 - misaligned)
malloc () 는 16 바이트 로 정렬 된 메모리 블록 을 되 돌려 줍 니 다. 수신 자 주소 가 16 바이트 로 정렬 되 지 않 았 다 면 정확 한 대상 지침 이 아 닐 수도 있 습 니 다.
앞 두 분, 뒤 두 분 다 자리 잡 았 어 요. - malloc 의 free list.
블록 이 풀 리 면 메모리 분배 기 는 free list 지침 을 기록 합 니 다. 나중에 풀 려 난 대상 을 사용 하면 isa 지침 의 앞 두 자리 와 뒤 두 자리 가 모두 설 치 됩 니 다.
모든 비트 가 역 - GC 의 free list 는 위의 malloc 의 free list 와 비슷 합 니 다. GC 의 free list 는 주소 값 이 잘못된 것 처럼 보이 지만 ~ address (역 작 동) 의 값 은 합 리 적 으로 보 입 니 다.
0xa1b1c1d 3 - CF container CoreFoundation containers 는 이 값 을 사용 하여 삭제 되 거나 비 워 진 항목 을 표시 합 니 다.
ASCII 텍스트 는 풀 려 있 는 대상 을 문자열 로 재배 치 하거나 풀 려 있 는 문자열 을 대상 으로 재배 치 하 는 것 일 수도 있 습 니 다. 메모리 가 경 계 를 넘 는 이유 일 수도 있 습 니 다. asciify 명령 을 사용 하여 서로 다른 바이트 정렬 모드 의 문자열 을 출력 하여 보기 편 하 게 합 니 다. 다음은 URL 과 관련 된 것 처럼 보 이 는 문자열 입 니 다.  % asciify 0x2e777777   ###.www###   ###www.###  
선택 기 추적 (선택 기 상호 작용)
컴 파일 최 적 화 는 호출 스 택 에서 두 번 째 단 계 를 가리 키 는 호출 점 (call site) 을 진정 으로 충돌 시 키 는 호출 이 아 닐 수도 있 습 니 다. 호출 이 성공 한 것 이 아니 라 이 방법의 끝 호출 (tail call) 으로 인해 충돌 할 수도 있 습 니 다. 바로 끝 호출 (tail call) 때 문 입 니 다.호출 스 택 에 표시 되 지 않 고 중간 호출 프레임 을 무시 할 수 있 습 니 다. selector 레지스터 를 사용 하여 실제 충돌 호출 을 확인 할 수 있 습 니 다.
 
하나의 selector 는 유일한 C 문자열 을 가리 키 고 있 습 니 다. 앞으로 새로운 시스템 에서 변 경 될 수 있 습 니 다. 하지만 지금 은 디 버 깅 에 편리 하 게 사용 할 수 있 습 니 다. debugger 에서 프로그램 이 무 너 지면 Debugger 콘 솔 을 열 고 위 표 에 있 는 selector 레지스터 를 사용 하여 다음 명령 을 수행 합 니 다.
    (gdb) x/s $ecx     0xa1029: "release"
Snow Leopard 시스템 에서 제공 하 는 충돌 로그 에 selector 이름 이 추가 되 었 습 니 다.
    Application Specific Information:     objc_msgSend() selector name: release
 
그 밖 에 충돌 로그 에서 selector 를 얻 는 것 은 어 려 운 일 입 니 다. Snow Leopard 까지 다음 방법 을 사용 할 수 있 습 니 다. 1. 충돌 로그 의 Thread State 에서 앞 표 에 열 거 된 selector 레지스터 값 을 대조 할 수 있 습 니 다. 예 를 들 어:    ecx: 0x000a1029
2. 충돌 로그 의 Binary Images 위치 에서 이 주 소 를 포함 하 는 미 러 (image) 를 찾 습 니 다. 항상 프로그램 자체 나 libobject. A. dylib 입 니 다. 해당 하 는 image 를 찾 지 못 하면 포기 하 세 요.    0x8b000 -   0x106ff7  libobjc.A.dylib ??? (???) <9b5973b7fa88f9aab7885530c7b278dd> /usr/lib/libobjc.A.dylib
3. 충돌 로그 에 열 거 된 미 러 와 일치 하 는 프로그램 파일 을 찾 습 니 다. UUID 를 사용 하여 일치 성 을 확인 할 수 있 습 니 다.    % dwarfdump -u /usr/lib/libobjc.A.dylib     UUID: 26650299-C6EA-B1C8-52D6-072AC874D400 (ppc) /usr/lib/libobjc.A.dylib     UUID: 9B5973B7-FA88-F9AA-B788-5530C7B278DD (i386) /usr/lib/libobjc.A.dylib     UUID: D2A4E8E1 - 3C1C - E0D9 - 2249 - 125B6DD621F 8 (x86 64) / usr / lib / libobject. A. dylib 는 시스템 버 전의 일치 성 을 동시에 확보 합 니 다.
4. 거울 에 있 는 SEL 의 오프셋 주 소 를 계산 합 니 다.    0xa1029 - 0x8b000 = 0x16029
5. 미 러 (image) 에 위치 한 C 문자열 을 인쇄 합 니 다. 정확 한 구 조 를 기억 하 십시오.    % otool -v -arch i386 -s __TEXT __cstring /usr/lib/libobjc.A.dylib | grep 16029     00016029  release
 
전재 출처 를 밝 혀 주 십시오:http://blog.csdn.net/horkychen
원문 주소: obj c msgSend () 에서 충돌 하 였 습 니 다.

좋은 웹페이지 즐겨찾기