函数调用重置传递的全局结构的字段

Function call resets passed global structs' fields

参考下面的代码:调用函数CheckSMS并传递结构*DB1后,根据strtok调用更新字段。此函数读取并解析文本消息,将其内容存储到 DB 结构的 char* 字段中。

在主循环中,我在调用CheckSMS函数之前和之后调用了Serial.println(DB1.last_order)。如果我收到了一条文本,订单会在主循环中正确打印,但是在下一次调用 CheckSMS 时,DB1.last_order 被清除,替换为 \n 或 NULL 或其他内容。我不明白为什么 DB1.last_order 不保留其值,而是每次调用 CheckSMS 时都会覆盖它。感谢您的帮助。

注意 - 所有文本消息都包含 "CMT+",因此只有在收到文本时才会写入 DB1。在没有收到文本时调用 CheckSMS 应该直接跳过。

  int CheckSMS(Robot *DB1) {

  int j = 0;
  char  response[100];
  char  *pch;
  unsigned long previous;

  memset(response, '[=10=]', 100);

  while(Serial2.available()>0){
       response[j] = Serial2.read();
       j++;
       Serial.println("inc");
  }

  delay(100);
  if (strstr(response, "CMT:") != NULL){ 
      DB1->new_message = strtok(response, " ,");
      DB1->last_phone = strtok(NULL, " ,");
      pch = strtok(NULL, " ,");
      DB1->last_date = strtok(NULL, " ,");
      DB1->last_time = strtok(NULL, " ,\n");
      DB1->last_order = strtok(NULL," ,\n");
      new_message = 1;  

  }

  else{
  }

  return 0;
}

strtok 函数 returns 指向您正在标记化的字符串,在您的例子中是本地数组 response。当函数 returns 时,response 数组超出范围并消失,使您的结构带有指向不再存在的字符串的指针,并给您 未定义的行为 .

您有几个解决方案:

  • 使用 malloc 动态分配字符串,但随后您必须将其保存在结构中,以便在完成结构
  • 后可以 free
  • 创建 response 数组 static,但随后对该函数的下一次调用将使用相同的数组引导旧数据进行更新
  • 传入一个字符串来存储响应并使用该字符串,该字符串的生命周期必须至少与结构一样长并且不要更改内容。字符串当然可以是结构本身的成员

Joachim 给出的答案是正确的,我只是想补充一点,您还可以更改 Robot 结构以包含 char 数组(例如:char new_message[MAX_BUF_CHARS]; 等)。确保其中有足够的 space。然后不分配从 strtok 返回的指针,而是复制其中的字符串。