如何诊断将缓冲区反序列化为结构的问题?
How can I diagnose my issue deserializing a buffer into a structure?
我正在尝试了解如何为此结构中的 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] = { '[=10=]' };
33 char src[MAX_FILENAME_LEN] = { '[=10=]' };
32 char dest[MAX_FILENAME_LEN] = { '[=10=]' };
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] = '[=10=]';
9
10 return buf;
11 }
12
13 int main(int argc, char **argv) {
14 char cmd_buf[CMD_LIMIT] = { '[=10=]' };
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
和 dest
的指针的空间是通过 cmd
的 malloc 给出的,而 strdup 是为(空字符以及所有内容)用于结构本身中的 C 字符串。给出了什么?
我已经尝试过替代方法,例如 malloc'ing,然后是 strncpy 或 memmove。
我只想补充一点,选择这些前导下划线是为了使函数名称不会与 common.h 中的名称冲突。这是用于重现问题的最小工作示例 - 不是我正在使用的原始代码。这同样适用于不释放字符串等。在构建这个小型测试应用程序时被忽略了。
print_cmd
简单地打印具有适当格式的结构,就像人们想象的那样。
这一行:
cmd = malloc(sizeof cmd);
为指向结构的指针分配足够的 space,但您需要为结构本身分配足够的 space。你可以用
解决这个问题
cmd = malloc(sizeof *cmd);
或
cmd = malloc(sizeof(struct command));
我正在尝试了解如何为此结构中的 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] = { '[=10=]' };
33 char src[MAX_FILENAME_LEN] = { '[=10=]' };
32 char dest[MAX_FILENAME_LEN] = { '[=10=]' };
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] = '[=10=]';
9
10 return buf;
11 }
12
13 int main(int argc, char **argv) {
14 char cmd_buf[CMD_LIMIT] = { '[=10=]' };
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
和 dest
的指针的空间是通过 cmd
的 malloc 给出的,而 strdup 是为(空字符以及所有内容)用于结构本身中的 C 字符串。给出了什么?
我已经尝试过替代方法,例如 malloc'ing,然后是 strncpy 或 memmove。
我只想补充一点,选择这些前导下划线是为了使函数名称不会与 common.h 中的名称冲突。这是用于重现问题的最小工作示例 - 不是我正在使用的原始代码。这同样适用于不释放字符串等。在构建这个小型测试应用程序时被忽略了。
print_cmd
简单地打印具有适当格式的结构,就像人们想象的那样。
这一行:
cmd = malloc(sizeof cmd);
为指向结构的指针分配足够的 space,但您需要为结构本身分配足够的 space。你可以用
解决这个问题cmd = malloc(sizeof *cmd);
或
cmd = malloc(sizeof(struct command));