2017-05-16 3 views
-1

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를보고 잘못된 참조 값을 표시 할 수 있습니까? 이 조각에서 사후에게 전체 기능을하지 않았다 때문에

+0

'this'가'NULL '이 아니며 유효한 주소를 가리키고 있는지 확인 했습니까? 스택 오버플로가 발생할 위험이 있습니까? 즉 현재 작업의 스택에서 어디에 위치하여 여유 공간이 있습니까? 'BLT' 자체는 스택을 사용해서는 안되지만, 이미 이상한 일이 생길 수도 있습니다. – unwind

+0

@unwind, 했어. 'this-> canx'는 전역 변수 CAN2와 동일한 주소를 가지고 있기 때문에 {this}는 'NULL'이 아니며 'this'가 이미 성공적으로 초기화되었다는 것을 의미합니다. 스택은 1KB입니다. 물론 문제 일 수 있습니다. 어떻게 찾아 낼 수 있을까요? –

+0

@judoka_acl은 스택 오버 플로우를 배제하기 위해 할당 된 스택 메모리의 맨 아래에 '0xdeadf00d'와 같은 카나리 값을 넣은 다음 카나리아가 살아 있는지 (즉 메모리에 여전히 초기 값). 스택이 할당 된 공간에서 커지면 카나리 값을 덮어 씁니다 (원점을 찾기가 어려울 것입니다 : /). 일부 컴파일러는 디버그 빌드와 비슷한/더 나은 기술을 제공하고 모든 함수 호출에서도 스택 유효성을 검사하지만 사소한 수동 카나리아는 프로덕션 빌드를 위해조차도 충분히 빠를 수 있습니다. – Ped7g

답변

0

문제점은 uVision : http://www.keil.com/support/docs/2824.htm에 있습니다.

uVision은 로컬 변수를 감시하는 것이 신뢰할 수 없도록 몇 가지 추가 최적화를 수행하고 있습니다.

0

난 단지 추측 할 수 있습니다

  1. 이 지역 변수 만 지정이 있지만, 그것은 당신의 프로그램에서 임의의 장소에서 사용되지 않으며 아마에서 제거 생성 된 코드
  2. 컴파일러에서 오류를 찾지 마십시오. 그들은 아주 좋고 나는 (나는 매우 활동적인 코더이다) 어떤 것도 발견하지 못했다. 누군가가 이렇게 말하면 항상 : "이것은 디스 어셈블리 목록이고, 컴파일러는 틀리다", 실수는 묻는 사람이 어딘가에서 행한다. 프로그램을 디버깅 할 때 디스 어셈블리를 잊어 버리십시오. 방금 시간 낭비.
+0

filt가 읽혀지면 내 질문을 업데이트하겠습니다. 힌트를 가져 주셔서 감사합니다. 나는 컴파일러에서 어떤 에러도 찾고 있지 않다. 나는 컴파일러가 잘못되었다고 말하고있다. 오류를 현지화하고 이상한 행동에 대해 질문하려고합니다. –

+0

@judoka_acl은 완전한 함수 호출을 게시합니다. 특정 상황에서 기능이 작동한다고해서 다른 기능에서 작동한다는 것을 의미하지는 않습니다. 버그는 공개하는 것이 훨씬 더 복잡한 경우가 많습니다. –

+0

오류는 내가 게시 한 코드에서 정확히 현지화되었습니다. 당신이 개인적으로 나에게 그것을 나눌 수 있다고 주장한다면, 나는 그 문제가 나머지 기능에 없다는 것을 1000 % 확신한다. 지금은 디버거가 잘못된 주소를 표시하고 있으며 코드에 문제가 전혀 없다는 생각을하고 있습니다. –

관련 문제