Как SSCANF может дать такие странные результаты? - PullRequest
0 голосов
/ 27 марта 2020

Я в 4-дневном бою с этим кодом:

  unsigned long baudrate = 0;
  unsigned char databits = 0;
  unsigned char stop_bits = 0;

  char parity_text[10];
  char flowctrl_text[4];

  const char xformat[] = "%lu,%hhu,%hhu,%[^,],%[^,]\n";
  const char xtext[] = "115200,8,1,EVEN,NFC\n";
  int res = sscanf(xtext, xformat, &baudrate, &databits, &stop_bits, (char*) &parity_text, (char*) &flowctrl_text);

  printf("Res: %d\r\n", res);
  printf("baudrate: %lu, databits: %hhu, stop: %hhu,   \r\n", baudrate, databits, stop_bits);
  printf("parity: %s \r\n", parity_text);
  printf("flowctrl: %s \r\n", flowctrl_text);

Возвращает:

Res: 5
Скорость передачи данных: 115200, Базы данных: 0, остановка : 1,
четность:
flowctrl: NF C

Базы данных и четность отсутствует!

На самом деле память под переменной parity равна '\ 0'VEN' \ 0 ', похоже, что первые символы были каким-то образом перезаписаны процедурой sscanf.

Возвращаемое значение sscanf равно 5, что предполагает: что он смог проанализировать ввод.

Моя конфигурация:

  • gccarmnoneeabi 7.2.1
  • Код Visual Studio 1.43.2
  • PlatformIO Core 4.3.1
  • PlatformIO Home 3.1.1
  • Lib ST-STM 6.0.0 (Mbed 5.14.1)
  • STM32F446RE (Nucleo-F446RE)

Я пытался (безуспешно):

  • компилировать с ОСРВ mbed и без
  • типов переменных uint8_t, uint32_t
  • gccarm версии: 6.3. 1, 8.3.1, 9.2.1
  • с использованием другого I DE (CLion + PlatformIO)
  • компиляция на другом компьютере (та же конфигурация)

Что на самом деле помогает:

  • создание переменных stati c
  • компиляция в онлайн-компиляторе Mbed

Поведение sscanf в целом очень непредсказуемо, иногда помогает смешивание порядка или типа данных переменных, но чаще всего они заканчиваются другим fl aws в выход.

1 Ответ

0 голосов
/ 27 марта 2020

Это заняло у меня больше времени, чем я хочу признаться. Но, как и большинство проблем, все оказалось очень просто.

  char parity_text[10];
  char flowctrl_text[4];

Необходимо изменить на:

  char parity_text[10] = {0};
  char flowctrl_text[5] = {0};

Массив flowctrl_text недостаточно велик для размера четыре, чтобы содержать «ДАЖЕ» и NULL прекращение. Если вы увеличите размер до 5, проблем не должно быть. На всякий случай я бы также инициализировал массивы на 0.

Как только я увеличил размер, у меня возникло 0 проблем с вашим существующим кодом. Позвольте мне знать, если это помогает.

...