C语言 这个结构中的值出了什么问题?

flvlnr44  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(136)

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);
}

字符串

a14dhokn

a14dhokn1#

1.这是parse_string()中分配pToken[5] = NULL的缓冲区溢出。我建议传入SCAN_EVENT_REQ并使用它来限制i < 5

  1. ev->event_names不能以“\0”终止,这将触发strtok()中需要字符串的未定义行为。运行<= en_size的循环或使用strcpy()
  2. sizeof EVENT_NAMES == 32所以char event_names[31]不够大。不要重复。在这种情况下是投影strlen(EVENT_NAMES) == 31,所以它应该是strlen(EVENT_NAMES) + 1,或者因为你有数组,所以只使用sizeof
    1.如果malloc失败了,你就不能使用ev了。使用exit(1)并不是不合理的,因为你可能对它无能为力。
    1.优化了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

相关问题