如何诊断将缓冲区反序列化为结构的问题?

时间:2019-01-24 16:53:37

标签: c pointers c-strings

我试图了解如何在此结构中为c字符串动态分配内存。请跳到代码下方的输出,并附上我的解释。

这是我正在运行的代码:

 NN #define USAGE "[get|put|quit] filenamesource filenamedest"
...
 20 enum cmd_type get_type(char *cmd) {
 21     if (0 == strncmp("put", cmd, 3)) {
 22         return PUT;
 23     }
 24     else if (0 == strncmp("get", cmd, 3)) {
 25         return GET;
 26     }
 27     else if (0 == strncmp("quit", cmd, 3)) {
 28         return QUIT;
 29     }
 30     else {
 31         return INV;
 32     }
 33 }
...
  0 int _recv_cmd(char *cmd_buf) {
 34     char type[MAX_FILENAME_LEN] = { '\0' };
 33     char src[MAX_FILENAME_LEN] = { '\0' };
 32     char dest[MAX_FILENAME_LEN] = { '\0' };
 31     size_t size = 0;
 30     enum error err = 0;
 29     struct command *cmd = NULL;
 28
 27     printf("Process %d received serialized command '%s'\n", getpid(), cmd_buf);
 26
 25     cmd = malloc(sizeof cmd);
 24     if (NULL == cmd) {
 23         perror("malloc");
 22         return -1;
 21     }
 20     if (5 != sscanf(cmd_buf, " %s %s %s %zu %u ", type, src, dest, &size, &err)) {
 19         fprintf(stderr, "sscanf failed to scan input.\n");
 18         free(cmd);
 17         return -1;
 16     }
 15
 14     printf("%s, %s, %s, %zu, %u\n", type, src, dest, size, err);
 13
 12     cmd->type = get_type(type);
 11     cmd->src = strdup(src);
 10     cmd->dest = strdup(dest);
  9     cmd->fsz = size;
  8     cmd->err = err;
  7
  6     print_cmd(cmd);
  5
  4     free(cmd);
  3
  2     return 0;
  1 }
...
  0 char * _get_input(char *buf) {
  1     // get input
  2     if (NULL == fgets(buf, CMD_LIMIT, stdin)) {
  3         fprintf(stderr, "fgets failed.\n");
  4         return NULL;
  5     }
  6     // remove newline
  7     int newline_pos = strcspn(buf, "\n");
  8     buf[newline_pos] = '\0';
  9
 10     return buf;
 11 }
 12
 13 int main(int argc, char **argv) {
 14     char cmd_buf[CMD_LIMIT] = { '\0' };
 15
 16     while(1) {
 17
 18         printf("Enter command of the form '%s':\n", USAGE);
 19
 20         _recv_cmd(_get_input(cmd_buf));
 21     }
 22
 23     exit(EXIT_SUCCESS);
 24 }

这是命令类型:

 29 struct command {
 30     enum cmd_type type;
 31     char *src;
 32     char *dest;
 33     size_t fsz;
 34     enum error err;
 35 };

这是我从运行编程中获得的输出。请注意,我在示例之间添加了空格。

➜  assignment01 git:(master) ✗ ./test
Enter command of the form '[get|put|quit] filenamesource filenamedest':
put hi hi 25 0
Process 53001 received serialized command 'put hi hi 25 0'
put, hi, hi, 25, 0
type: 2, source:  , dest: , size: 25, err: 0
Enter command of the form '[get|put|quit] filenamesource filenamedest':
put  hi hi 25 0
Process 53022 received serialized command 'put  hi hi 25 0'
put, hi, hi, 25, 0
type: 2, source: 'p, dest: , size: 25, err: 0
Enter command of the form '[get|put|quit] filenamesource filenamedest':
get  what is 30 1
Process 53022 received serialized command 'get  what is 30 1'
get, what, is, 30, 1
type: 1, source: what, dest: is, size: 30, err: 1

从输出中可以看到,缓冲区的内容与我期望的样子完全一样(“ received serialized ...”)。那里没什么异常。

直接在提示符下的行上的输出来自该行

printf("%s, %s, %s, %zu, %u\n", type, src, dest, size, err);

表示sscanf完全按照我的预期工作。那么,为什么cmd的内容如此混乱?

我了解到,src的malloc给了指向字符串destcmd的指针的空间,而strdup则为(空字符和其他所有内容)分配了空间)以获取结构本身中的C字符串。有什么作用?

我已经尝试了其他方法,例如malloc'ing,然后是strncpy或memmove。

我要补充一点的是,选择了这些前导下划线,以便函数名称与common.h不冲突。这是用于重新创建问题的最低限度的工作示例-而不是我正在使用的原始代码。这同样适用于不释放字符串等。在构建此小型测试应用程序时会被忽略。

print_cmd只是简单地用适当的格式打印了结构的结构即可。

1 个答案:

答案 0 :(得分:1)

此行:

cmd = malloc(sizeof cmd);

为指向结构的指针分配足够的空间,但是您需要为结构本身提供足够的空间。您可以使用

解决此问题
cmd = malloc(sizeof *cmd);

cmd = malloc(sizeof(struct command));