struct中的可变长度数组

时间:2013-03-04 21:38:20

标签: c arrays struct malloc

我正在用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)

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

我正在编写的实际上是一个解析器,因此命令会被传递到parse函数(它描述当前状态,给解析器提示接下来会发生什么)和下一个命令(从输入“line”派生) “)被退回。 “context”在解析函数结束时是free-d,新命令返回 - 然后将返回到“parse”并输入下一个“行”。

有人可以建议为什么会发生这种情况吗?

非常感谢。

2 个答案:

答案 0 :(得分:11)

为结构分配内存时,只有指针大小被分配给* desc。正如有人已经指出的那样,你必须为空间(数组内容)指向内存分配内存。我的答案的目的是显示略有不同的方式。 由于有一个指针* desc增加了一个单词(sizeof指针)的结构大小,你可以安全地在你的结构中有一个可变长度数组hack来减少结构大小。

这里有你的结构应该是什么样的,请注意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. 使用desc:

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

  2. 只有当成员位于结构的末尾,保存结构大小,保存指针间接时,才能使用此hack,如果数组长度是结构实例特定的,则可以使用

答案 1 :(得分:9)

您必须单独分配desc和数据。

当你分配struct命令* cmd时,会为你的decs和data指针分配内存。描述和数据必须单独进行索引。

所以分配你的命令

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

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

cmd->desc = malloc( sizeof(char )*100);