在程序中进行函数调用后,控制跳转到未指定的内存位置

After making function call in the programme ,control is jumping into the unspecified memory location

我正在开发一个 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] = '[=10=]';           //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] = '[=10=]';            //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] = '[=10=]';               //GPGGA longitude

    }
else
    {
        /*do nothing*/
    }
}

对我来说听起来像是腐败。很可能是堆栈溢出或堆栈损坏。我会在代码中的不同点停止调试器,并查看已被压入堆栈的 link 寄存器,看看它是否在执行期间的任何时候发生变化。它也可能因中断或其他功能而损坏。这需要了解 ARM/C 调用约定,因此您可能需要做一些研究。

这听起来像是覆盖 return 地址的经典缓冲区溢出。检查 tempbuff。 str_cpy() 可能是一个好的开始(如果它像 strcpy(),它将溢出缓冲区,因为源不是 NUL-终止)。您可以将缓冲区大小传递给它以防止在所有情况下溢出(即使源格式错误)。

剩余的代码也很漂亮 "optimistic",因为如果输入损坏,它将表现出 未定义的行为 (UB)。如果没有适当的范围检查,我不会接受这样的代码!请记住,所有外部(非自生成)数据都可能已损坏。根据墨菲定律,

另外,不清楚为什么要先将数据复制到缓冲区。直接从输入缓冲区解析它会更快更容易。

正如安德鲁所说,这听起来像是堆栈损坏。一种可能是您正在写超出 tmpbuff 末尾的部分,在我看来好像是在 str_cpy 中。您可以尝试改用 strncpy,或者(大量)增加 tmpbuff 的大小;如果这解决了问题,那么要解决的问题是 rx 缓冲区不会像您的代码所假设的那样为您提供长度最多为 99 的字符串。

我猜你正在使用 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 的填充方式。这是因为您正在处理临时缓冲区中的 RX 消息。 我猜想促使您将收到的消息复制到临时缓冲区的原因是 RX 缓冲区必须由另一个 task/interrupt.

在那种情况下,是否确保在复制到 tempbuffer 期间不会覆盖 RX 缓冲区?

无论如何,在执行此操作之前,您必须始终检查消息的完整性:我希望您在验证 RX 缓冲区之前对接收到的消息进行校验和。

最后一点,这段代码没有意义:

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

您可以将其更改为:

loop1 = 0;
loop2++;   

编辑:

据@Weather Vane 报道:在 unsigned charint 变量之间切换从来都不是一个好主意。