相对较新的C年,我会很容易承认有些事情我认为我理解,但可能不会欣赏所有的细微差别.这是从我编写的一个更复杂的程序中摘录的MWE.它可以很好地编译和运行,但测试表明ev->pin的值最初是正确的,但在不相关的函数调用后是不正确的(查找?在代码中)看起来内存不知何故被践踏了,但我不知道是怎么回事.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define SCAN_EVENT_COUNT 5
#define PIN_ASSIGNMENTS {7, -1, 1, 13, 4}
#define EVENT_NAMES "first-second-third-fourth-fifth"

void init_scan_events();
int parse_string(char pInputString[],
                 char *Delimiter,
                 char *pToken[]);

struct scan_events
{
  char event_names[31];
  char *pEvent[SCAN_EVENT_COUNT];
  int pin[SCAN_EVENT_COUNT];
};

int main(void)
{
  init_scan_events();
  return (0);
}

/**
 * the following function from https://stackoverflow.com/a/2091906/633251
 * Note that `strtok` expects a `char * string` and `char * delimiter` as arguments.
 **/

int parse_string(char pInputString[],
                 char *Delimiter,
                 char *pToken[])
{
  int i = 0;
  pToken[i] = strtok(pInputString, Delimiter); // get first token
  i++;
  while ((pToken[i] = strtok(NULL, Delimiter)) != NULL) // get the rest of the tokens
  {
    i++;
  }
  return i;
}

void init_scan_events()
{
  char en[] = EVENT_NAMES;
  int en_size = strlen(en);
  int size = SCAN_EVENT_COUNT;
  int pin[] = PIN_ASSIGNMENTS;

  int token_count = 0;
  char *Delim = "-";
  int i;

  struct scan_events *ev = malloc(sizeof(struct scan_events));
  if (ev == NULL)
  {
    printf("Allocation failed\n");
  }

  for (int i = 0; i < en_size; i++) // copy EVENT_NAMES
  {
    ev->event_names[i] = en[i];
  }

  for (int i = 0; i < size; i++) // copy PIN_ASSIGNMENTS
  {
    ev->pin[i] = pin[i];
  }

  for (int i = 0; i < size; i++)
  {
    printf("% d ", ev->pin[i]); // ??? inspect pin values: correct!
  }
  printf("\n");

  token_count = parse_string(ev->event_names, Delim, ev->pEvent); // tokenize EVENT_NAMES

  for (int i = 0; i < size; i++)
  {
    printf("% d ", ev->pin[i]); // ??? check pin values: corrupted!
  }
  printf("\n");

  free(ev);
}

推荐答案

  1. 这是赋值pToken[5] = NULLparse_string()中的缓冲区溢出.我建议传入Scan_Event_Count并使用它来限制i < 5.

  2. ev->event_names不能‘\0’终止,这将触发strtok()中需要字符串的未定义行为.要么将循环运行到<= en_size,要么使用strcpy().

  3. Sizeof EVENT_NAMES==32,因此char event_names[31]不够大.不要重复那些东西.在本例中是投影strlen(EVENT_NAMES) == 31,因此它应该是strlen(EVENT_NAMES) + 1,或者像您已有的数组一样,只使用sizeof.

  4. 如果Malloc失败,你不能使用ev.这并不是不合理的exit(1),因为无论如何你可能对它无能为力.

  5. 优化了init_scan_events()(客场),专注于上述问题.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define DELIM "-"
#define SCAN_EVENT_COUNT 5
#define PIN_ASSIGNMENTS (int []) {7, -1, 1, 13, 4}
#define EVENT_NAMES "first-second-third-fourth-fifth"

struct scan_events {
    char event_names[sizeof EVENT_NAMES];
    char *pEvent[SCAN_EVENT_COUNT];
    int pin[SCAN_EVENT_COUNT];
};

int parse_string(char pInputString[], const char *Delimiter, size_t n, char *pToken[]);
void print(struct scan_events *ev);

int parse_string(char pInputString[], const char *Delimiter, size_t n, char *pToken[]) {
    int i = 0;
    for(; i < n; i++) {
        pToken[i] = strtok(i ? NULL : pInputString, Delimiter); // get first token
        if(!pToken[i]) break;
    }
    return i;
}

void print(struct scan_events *ev) {
    for (int i = 0; i < SCAN_EVENT_COUNT; i++)
        printf("% d%c", ev->pin[i], i + 1 < SCAN_EVENT_COUNT ? ' ' : '\n');
}

int main(void) {
    struct scan_events ev;
    strcpy(ev.event_names, EVENT_NAMES);
    memcpy(ev.pin, PIN_ASSIGNMENTS, sizeof PIN_ASSIGNMENTS);
    print(&ev);
    parse_string(ev.event_names, DELIM, SCAN_EVENT_COUNT, ev.pEvent);
    print(&ev);
}

和示例运行:

 7 -1  1  13  4 
 7 -1  1  13  4 

C++相关问答推荐

GCC:try 使用—WError或—pedantic using pragmas

通过MQTT/蚊子发送大文件—限制在4MB

如何在IF语句中正确使用0.0

Win32API Wizzard97 PropSheet_SetWizButton不工作

将宏值传递给ARM链接器,该链接器将变量放置在特定位置

如何捕捉只有换行符或空格字符缓冲区的边缘大小写

VS代码';S C/C++扩展称C23真关键字和假关键字未定义

在C++中访问双指针

如何将另一个数组添加到集合中,特别是字符串?

为什么Fread()函数会读取内容,然后光标会跳到随机位置?

C将数组传递给函数以修改数组

为什么电路板被循环删除?

链表删除 node 错误

为什么我的二叉树删除删除整个左部分的树?

如何在C宏定义中包含双引号?

我错误地修复了一个错误,想了解原因

将数组中的所有元素初始化为 struct 中的相同值

Struct 内的数组赋值

C 语言中霍尔分区的快速排序算法

设置具有非零终止字符串的大整数