Windows 7에서 Keil uVison 4 사용 stm32f105의 c 프로젝트에서 매우 이상한 동작을 보입니다. 내가 디버거와 함께 그것을 점검하고, 몇 시간 동안 오류를 추적 한 후에 다른 프로젝트 기능에서 이미 테스트 한 오류를 현지화했다. 다음과 같이 보입니다 :STM32f105 BLT 명령어가 로컬 변수를 재배치합니다.
uint8_t can_add_filter_mask(can_t* this, uint32_t id, uint32_t id_mask, can_frm_type_t type, can_frm_type_t type_mask)
{
CAN_FilterInitTypeDef filt;
/* Empty filter available? */
if(this->filter_len >= 14)
{
return FALSE;
}
/* Select filter number */
if(this->canx == CAN1)
filt.CAN_FilterNumber = this->filter_len + 0;
else
filt.CAN_FilterNumber = this->filter_len + 14;
this->filter_len++;
...
//filt is read
CAN_FilterInit(&filt);
}
구조체 filt가 변경되지 않았으므로! 그리고 나는 dissassembly을 변경하고 다음의 (나는 그것이 있다고 미안 해요 조금 긴) :
108: uint8_t can_add_filter_mask(can_t* this, uint32_t id, uint32_t id_mask, can_frm_type_t type, can_frm_type_t type_mask)
0x08001B22 BD70 POP {r4-r6,pc}
109: {
110: CAN_FilterInitTypeDef filt;
111:
112: /* Empty filter available? */
0x08001B24 E92D41FF PUSH {r0-r8,lr}
0x08001B28 4604 MOV r4,r0
0x08001B2A 460D MOV r5,r1
0x08001B2C 4690 MOV r8,r2
0x08001B2E 461E MOV r6,r3
0x08001B30 9F0A LDR r7,[sp,#0x28]
113: if(this->filter_len >= 14)
114: {
0x08001B32 7C20 LDRB r0,[r4,#0x10]
0x08001B34 280E CMP r0,#0x0E
0x08001B36 DB03 BLT 0x08001B40
115: return FALSE;
0x08001B38 2000 MOVS r0,#0x00
151: }
152:
153: /******************************************************************************/
154: void can_clr_filter(can_t* this)
0x08001B3A B004 ADD sp,sp,#0x10
0x08001B3C E8BD81F0 POP {r4-r8,pc}
119: if(this->canx == CAN1)
0x08001B40 4970 LDR r1,[pc,#448] ; @0x08001D04
0x08001B42 6820 LDR r0,[r4,#0x00]
0x08001B44 4288 CMP r0,r1
0x08001B46 D103 BNE 0x08001B50
120: filt.CAN_FilterNumber = this->filter_len + 0;
121: else
0x08001B48 7C20 LDRB r0,[r4,#0x10]
0x08001B4A F88D000A STRB r0,[sp,#0x0A]
0x08001B4E E004 B 0x08001B5A
122: filt.CAN_FilterNumber = this->filter_len + 14;
0x08001B50 7C20 LDRB r0,[r4,#0x10]
0x08001B52 300E ADDS r0,r0,#0x0E
0x08001B54 B2C0 UXTB r0,r0
0x08001B56 F88D000A STRB r0,[sp,#0x0A]
123: this->filter_len++;
124:
125: /* Select mask mode */
0x08001B5A 7C20 LDRB r0,[r4,#0x10]
0x08001B5C 1C40 ADDS r0,r0,#1
0x08001B5E 7420 STRB r0,[r4,#0x10]
내가 조립 전문가,도에서 ARM 전문가는 아니지만 어셈블리에 약간의 프로그래밍을 한 그리고 나에게 그것은 나빠 보이지 않는다. 내가 이상하게 느낀 점은 그 사이에 다른 함수 인 can_clr_filter의 일부 였기 때문에 컴파일러가 일부 코드를 재사용하는 것처럼 보였으 나 모든 최적화가 해제되어있는 것처럼 보였습니다. 흥미로운 부분은 내가 filt.CAN_FilterNumber
변수의 주소를 확인하는 경우, 그것은 0x20002252를 해결하기 위해 주소 0x20002262에서 라인
0x08001B36 DB03 BLT 0x08001B40
후 변경이었다. 그래서 모든 변화는 기억의 다른 곳에서 적용되었습니다 !! 변수가 정적으로 선언 된 후에는 문제가 사라졌습니다. 실제 상황에서 내게 미스터리가 있습니다 ... 어떻게 명령 BLT가 다른 주소로 로컬 변수를 재배치 할 수 있습니까? 또는 uVision 디버거가 & filt.CAN_FilterNumber를보고 잘못된 참조 값을 표시 할 수 있습니까? 이 조각에서 사후에게 전체 기능을하지 않았다 때문에
'this'가'NULL '이 아니며 유효한 주소를 가리키고 있는지 확인 했습니까? 스택 오버플로가 발생할 위험이 있습니까? 즉 현재 작업의 스택에서 어디에 위치하여 여유 공간이 있습니까? 'BLT' 자체는 스택을 사용해서는 안되지만, 이미 이상한 일이 생길 수도 있습니다. – unwind
@unwind, 했어. 'this-> canx'는 전역 변수 CAN2와 동일한 주소를 가지고 있기 때문에 {this}는 'NULL'이 아니며 'this'가 이미 성공적으로 초기화되었다는 것을 의미합니다. 스택은 1KB입니다. 물론 문제 일 수 있습니다. 어떻게 찾아 낼 수 있을까요? –
@judoka_acl은 스택 오버 플로우를 배제하기 위해 할당 된 스택 메모리의 맨 아래에 '0xdeadf00d'와 같은 카나리 값을 넣은 다음 카나리아가 살아 있는지 (즉 메모리에 여전히 초기 값). 스택이 할당 된 공간에서 커지면 카나리 값을 덮어 씁니다 (원점을 찾기가 어려울 것입니다 : /). 일부 컴파일러는 디버그 빌드와 비슷한/더 나은 기술을 제공하고 모든 함수 호출에서도 스택 유효성을 검사하지만 사소한 수동 카나리아는 프로덕션 빌드를 위해조차도 충분히 빠를 수 있습니다. – Ped7g