【问题标题】:segmentation fault on some strtok calls某些 strtok 调用的分段错误
【发布时间】:2017-03-03 23:26:27
【问题描述】:

这是一个在循环中运行的函数。基本上,应用程序从 Arduino 接收消息并将消息发送到此函数:

void parseMessage(char *message){

    char *sensor_num="";
    char *value="";
    char *percentage="";
    char *delimiter = "|";

    sensor_num = strtok(message , delimiter);
    value = strtok(NULL, delimiter);
    percentage = strtok(NULL, delimiter);

    // Do stuff with values
}

它会持续运行一段时间,但有时我会在 value = strtok(NULL, delimiter); 部分遇到段错误。

到达的消息是这样的:

1|123|50|

以及调用parseMessage的主函数

int main() {

  SYS_LOG_INFO("Opening device... ");
  int BLUETOOTH = open("/dev/tty.HC-05-DevB", O_RDONLY | O_NOCTTY | O_NONBLOCK);
  SYS_LOG_INFO("Opened!");

  struct termios tty;
  struct termios tty_old;
  memset (&tty, 0, sizeof tty);

  /* Error Handling */
  if (tcgetattr(BLUETOOTH, &tty) != 0) {
    SYS_LOG_ERROR("Error on read Bluetooth.");
    return 1;
  }

  /* Save old tty parameters */
  tty_old = tty;

  /* Set Baud Rate */
  cfsetospeed (&tty, (speed_t)B9600);
  cfsetispeed (&tty, (speed_t)B9600);

  /* Setting other Port Stuff */
  tty.c_cflag     &=  ~PARENB;        // Make 8n1
  tty.c_cflag     &=  ~CSTOPB;
  tty.c_cflag     &=  ~CSIZE;
  tty.c_cflag     |=  CS8;

  tty.c_cflag     &=  ~CRTSCTS;       // no flow control
  tty.c_cc[VMIN]  =   1;
  tty.c_cc[VTIME] =   5;
  tty.c_cflag     |=  CREAD | CLOCAL; // turn on READ & ignore ctrl lines

  /* Make raw */
  cfmakeraw(&tty);

  /* Flush Port, then applies attributes */
  tcflush(BLUETOOTH, TCIFLUSH);
  if ( tcsetattr ( BLUETOOTH, TCSANOW, &tty ) != 0) {
    SYS_LOG_ERROR("Error on flush port.");
    return 1;
  }

  int n = 0;
  char buf[255];

  SYS_LOG_INFO("Starting to read data...");
  do {
    n = read(BLUETOOTH, &buf, sizeof buf);

    if (n > 0) {
      printf("buf = %s\n", buf);
      parseMessage(buf);
      memset(&buf, '\0', sizeof buf);
    }

    usleep(500000);  /* sleep for 100 milliSeconds */
  } while(1);

  return 0;
}

【问题讨论】:

  • 问题很可能不在于您的函数,而在于提供给它的数据。
  • 你能显示调用parseMessage的代码吗?
  • 请在再次询问之前检查strtok的返回值。 if(sensor_num != NULL) { value = strtok(NULL, delimiter); } 同上下一项。向您提供数据:始终检查,永远不要假设它是正确的。
  • @Weather Vane:关于检查数据馈送的权利。但是“不检查strtok的返回值”并不能解释崩溃,因为strtok一旦到达终点就会返回另一个NULL,对吧?
  • 吉尔伯特,请提供调用parseMessage的代码;也许您传递了一个缺少字符串终止字符的字符串,或者让strtok 以其他方式在不允许这样做的位置引入它的标记分隔'\0'-character。

标签: c segmentation-fault strtok


【解决方案1】:

1.由于strtokparseMessage内部被调用,buf应该是nul-terminate,否则可能会出现分段错误。试试下面的代码:

char buf[255]={0};

SYS_LOG_INFO("Starting to read data...");
n = read(BLUETOOTH, &buf, sizeof(buf)-1);

if (n > 0) {
  buf[n]=0;
  printf("buf = %s\n", buf);
  parseMessage(buf);
}

2。 strtok 不可重入,请改用 strtok_r。有时,这可能会导致奇怪的问题。

【讨论】:

    【解决方案2】:

    我从 Arduino 收到一些不一致的数据。

    所以,我解决了在将数据发送到解析之前使用正则表达式检查数据的问题。

    谢谢大家

    【讨论】:

      猜你喜欢
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2023-03-08
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多