6

我正在用 C 编写一个应用程序(作为初学者),我正在努力在包含可变长度数组的结构中获取损坏的数据。我在 cprogramming.com 和 cert.og/secure-coding 的论坛帖子中发现了类似的问题。我以为我找到了正确的解决方案,但似乎没有。

结构看起来像这样;

typedef struct {
    int a;
    int b;
} pair;

typedef struct {
    CommandType name;
    pair class;
    pair instr;
    pair p1;
    pair p2;
    pair p3;
    CommandType expected_next;
    char* desc;
    int size;
    pair sw1;
    pair sw2;
    pair* data;
} command;

有问题的是“命令”。对于“命令”的任何给定实例(或任何正确的短语),将设置不同的字段,尽管在大多数情况下,尽管在不同的实例中设置了相同的字段。

我遇到的问题是在尝试设置 expected_next、name、sw1、sw2、size 和 data 字段时。数据字段越来越损坏。我正在为这样的结构分配内存;

void *command_malloc(int desc_size,int data_size)
{
    return malloc(sizeof(command) +
                  desc_size*sizeof(char) +
                  data_size*sizeof(pair));
}

command *cmd;
cmd = command_malloc(0, file_size);

但是当我(漂亮地)打印生成的 cmd 时,数据字段的中间似乎是随机垃圾。我已经逐步使用 gdb 并且可以看到正确的数据正在加载到该字段中。似乎只有当命令被传递给不同的函数时,它才会被破坏。此代码在函数内部调用,例如;

command* parse(char *line, command *context)

漂亮的打印发生在另一个函数中;

void pretty_print(char* line, command* cmd)

我曾以为我做的事情是正确的,但显然不是。据我所知,我构造了该结构的其他实例没问题(我为这个重复了这些方法),但它们不包含任何可变长度数组,而且它们的漂亮打印看起来很好——这让我很担心,因为它们也有可能被破坏,但破坏不太明显。

我正在写的实际上是一个解析器,所以一个命令被传递到解析函数中(它描述了当前状态,提示解析器接下来会发生什么)和下一个命令(来自输入“行”)是回来。“context”在 parse 函数的末尾是 free-d,新命令将被返回 - 然后将通过下一个“line”输入传递回“parse”。

任何人都可以就为什么会发生这种情况提出任何建议吗?

非常感谢。

4

2 回答 2

11

当你为结构分配内存时,只有一个指针大小被分配给 *desc。正如有人已经指出的那样,您必须将内存分配给 desc 指向的空间(数组内容)。我回答的目的是展示稍微不同的方法。由于有一个指针 *desc 会增加一个字的结构大小(sizeof 指针),因此您可以安全地在结构中使用可变长度数组来减少结构大小。

这是您的结构应该是什么样子,请注意 desc[] 已被拉到结构的末尾:

typedef struct {
    CommandType name;
    pair class;
    pair instr;
    pair p1;
    pair p2;
    pair p3;
    CommandType expected_next;
    int size;
    pair sw1;
    pair sw2;
    pair* data;
    char desc[];
} command;

现在,1. 为包含数组大小的命令分配内存:

 command *cmd = malloc(sizeof(command) + desc_length);
  1. 使用说明:

    cmd->desc[desc_length -1] = '\0';

此 hack 仅在成员位于结构末尾时才有效,节省结构大小,节省指针间接,如果数组长度特定于结构实例,则可以使用。

于 2014-05-02T04:24:46.690 回答
9

您必须分别分配 desc 和 data。

当您分配结构命令 *cmd 时,将为您的 decs 和数据指针分配内存。Desc 和 data 必须分开分配。

所以分配你的命令

command *cmd =  malloc(sizeof(command));

然后为数据分配内存或
为 desc 分配 desc 示例:

cmd->desc = malloc( sizeof(char )*100);
于 2013-03-04T21:40:10.930 回答