2015-05-20 21 views
0

我正在開發一個gps代碼,它從gps獲取原始數據並解碼數據並將其保存到受尊重的變量(數組)中。每當我進行函數調用時,它都會執行直到函數結尾的函數語句,即「}」,然後控制進入一些未指定的存儲單元,並將控制權交給主函數。
它爲什麼會發生?沒有使用微控制器,代碼在編譯器中工作正常,爲什麼?有什麼步驟需要注意微控制器寄存器嗎?在程序中進行函數調用後,控制跳轉到未指定的內存位置

void gps_Gpgga_data_pro_funct(void) 
{ 
int   loop1 , loop2 , loop3 ; 

unsigned char commapos = 0;   //to hold the comma position 
unsigned char tempbuff[100];  //temparary buffer 

str_cpy(tempbuff,aa_GPS_GPGGA_RxBuffer); //received data taking into tempbuff 

if(tempbuff[3] == 'G' && tempbuff[4] == 'G' && tempbuff[5] == 'A') 
    { 
     loop1 = 0; 
     loop2 = 7; 
      while(tempbuff[loop2] != COMMA)    //getting the time 
      { 
      gga_time[loop1] = tempbuff[loop2]; 
      loop1 ++; 
      loop2 ++; 
      } 
           //storing the comma position in a variable. 
      gga_time[loop1] = '\0';   //GPGGA time 
      commapos = loop2 ; 
      loop1 = 0; 
      loop2 = 0; 
      loop2 = commapos + 1;    //setting the position for latitude 
      while(tempbuff[loop2] != COMMA)  //receiving the latitude value 
      { 
      gga_lat[loop1] = tempbuff[loop2] ; 
      loop2 ++; 
      loop1 ++; 
      } 
      commapos = loop2;      //saving the commaposition 
      gga_lat[loop1] = '\0';   //GPGGA latitude 

      loop1 = 0; 
      loop2 = 0; 
     loop2 = commapos + 3; 

      while(tempbuff[loop2] != COMMA)   // receiving the longitude value 
      { 
      gga_long[loop1] = tempbuff[loop2] ; 
      loop1 ++; 
      loop2 ++; 
      } 
      commapos = loop2 ; 
      gga_long[loop1] = '\0';    //GPGGA longitude 

    } 
else 
    { 
     /*do nothing*/ 
    } 
} 
+0

當輸入中沒有足夠的COMMA或者輸入長度超過99個字節時會發生什麼? –

+0

這是我從gps連續獲取的原始數據。 $ GPGGA,060723.00,1234.5678,N,1234.5678,E ,,, M ,, M ,, * 81.從這個函數基於逗號位置我將這些值存儲到數組中。 –

+1

不要依賴這個輸入!始終準備在輸入中輸入無效字符! – Olaf

回答

3

我想你正在使用NMEA 0183 GPS標準協議。

消息是<CR> <LF>終止,而不是NULL終止。

然後檢查你是不是使用字符串函數來完成這項工作。

我的意思是STR_CPY有看起來像如下:

str_cpy(char *tempbuff, char *aa_GPS_GPGGA_RxBuffer, uint8_t bufferlength) 
{ 
    for (int i=0; i<bufferLength; i++) 
    { 
     *(tempbuff+i) = *(aa_GPS_GPGGA_RxBuffer+i); 
    } 
} 

還有一個問題,我認爲你的應用程序可能有是aa_GPS_GPGGA_RxBuffer填充方式。這是因爲您正在應對臨時緩衝區中的RXMessage。 我想驅動你將接收到的消息複製到tempbuffer的原因是RX緩衝區必須由另一個任務/中斷重新填充。

在這種情況下,是否確保在複製到tempbuffer期間RX緩衝區不能被覆蓋?

無論如何,在執行此操作之前,您總是需要檢查您的消息的完整性:我希望您在驗證RX緩衝區之前執行了接收消息的校驗和。

最後的小東西,這個代碼是沒有意義的:

commapos = loop2 ; 
loop1 = 0; 
loop2 = 0; 
loop2 = commapos + 1; 

,你可以把它改成:

loop1 = 0; 
loop2++; 

編輯:

由於repored通過@Weather葉片:在unsigned charint之間切換絕不是一個好主意。

+1

重申您對'commapos'的最後評論,在'unsigned char'和'int'變量之間切換遲早會導致流淚。 –

+0

的變化幫了我很大的忙。 –

0

聽起來像腐敗給我。最有可能的堆棧溢出或堆棧損壞。我會在代碼中的不同位置停下調試器,並查看已經壓入堆棧的鏈接寄存器,並查看它在執行過程中是否隨時發生變化。它也可能從中斷或其他函數中被破壞。這將需要了解ARM/C調用約定,因此您可能需要進行一些研究。

+0

來自中斷的損壞的可能性要比格式錯誤的輸入數據(接收期間的損壞或意外輸入)低得多。至少應該總是檢查外部輸入。從中斷中發現腐敗實際上是a **中發現的一種痛苦。 – Olaf

2

這聽起來像覆蓋返回地址的經典緩衝區溢出。檢查溫度補償。 str_cpy()可能是一個好的開始(如果它像strcpy(),它會溢出緩衝區是源不是NUL-終止)。您可能會將緩衝區大小傳遞給它以防止在所有情況下溢出(即使源錯誤)。

其餘代碼也非常「樂觀」,因爲如果輸入已損壞,它將顯示未定義的行爲(UB)。沒有適當的範圍檢查,我不會接受這樣的代碼!請記住,所有外部(而非自己生成的)數據可能已損壞。並根據墨菲定律

此外,您不清楚爲什麼您首先將數據複製到緩衝區。從輸入緩衝區直接解析它會更快更容易。

+0

當我調試代碼時,它正在成功執行語句,直到函數的「}」,然後它進入未指定的內存位置。在調試選項的幫助下,我觀察到彙編代碼,有控制正在跳入未規定的內存中,將控制權交給調用函數。 –

+0

如果它沒有返回給調用者,則在進一步的調試中沒有用處。這是一個明確的標誌,返回地址已被破壞,導致UB。所以,你應該遵循我的回答,因爲這正是緩衝區溢出時會發生的情況(除非你的CPU有升序堆棧 - 不太可能)。 – Olaf

+0

@LP回答地址:如果'str_cpy'需要一個''\ 0''終結符,它會跳過'CR/LF'並在本地緩衝區找到'\ 0''的地方溢出。 –

0

正如安德魯所說,這聽起來像堆棧腐敗。一種可能性是,你正在寫tmpbuff的結尾,而且它看起來好像在str_cpy中。你可以嘗試使用strncpy,或者(大量)增加tmpbuff的大小;如果這樣排序的話,那麼需要解決的問題是,rx緩衝區不會像您的代碼所假定的那樣給您提供長度最多爲99的字符串。

相關問題