简体   繁体   English

结构中的可变长度数组

[英]Variable length arrays in struct

I'm writing an application in C (as a beginner) and I'm struggling with getting corrupted data inside a struct that contains a variable length array. 我正在用C语言编写一个应用程序(作为初学者),我正努力在包含可变长度数组的结构中获取损坏的数据。 I found similar issues described in forum posts on cprogramming.com and also on cert.og/secure-coding. 我在cprogramming.com和cert.og / secure-coding的论坛帖子中发现了类似的问题。 I thought I'd had found the right solution, but it seems not. 我以为我已经找到了正确的解决方案,但似乎没有。

The struct looks like this; 结构看起来像这样;

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;

With the problematic one being "command". 有问题的是“命令”。 For any given instance (or whatever the correct phrase would be) of "command" different fields would be set, although in most cases the same fields are set albeit in different instances. 对于“命令”的任何给定实例(或任何正确的短语),将设置不同的字段,尽管在大多数情况下,尽管在不同的实例中设置了相同的字段。

The problem I have is when trying to set the expected_next, name, sw1, sw2, size and data fields. 我遇到的问题是尝试设置Expected_next,名称,sw1,sw2,大小和数据字段时。 And it's the data field that's getting corrupt. 而且是数据字段正在损坏。 I'm allocating memory for the struct like this; 我正在为这种结构分配内存;

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

But when I (pretty) print the resulting cmd, the middle of the data field appears to be random garbage. 但是,当我(漂亮)打印生成的cmd时,数据字段的中间似乎是随机垃圾。 I've stepped through with gdb and can see that the correct data is getting loaded into the the field. 我已经遍历了gdb,可以看到正确的数据正在加载到该字段中。 It appears that it's only when the command gets passed to a different function that it gets corrupted. 看来只有当命令传递给另一个函数时,它才会被破坏。 This code is called inside a function such as; 此代码在函数中调用,例如;

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

And the pretty-print happens in another function; 精美的图片出现在另一个函数中;

void pretty_print(char* line, command* cmd)

I had thought I was doing things correctly, but apparently not. 我以为我做的事正确,但显然不行。 As far as I can tell, I construct other instances of the struct okay (and I duplicated those approaches for this one) but they don't contain any variable length array in them and their pretty-prints looks fine - which concerns me because they might also be broken, but the breakage is less obvious. 据我所知,我构建了该结构的其他实例(并为该实例复制了这些方法),但它们中不包含任何可变长度数组,并且它们的漂亮外观看起来还不错-这对我来说很担心,因为它们也可能会断裂,但断裂不太明显。

What I'm writing is actually a parser, so a command gets passed into the parse function (which describes the current state, giving hints to the parser what to expect next) and the next command (derived from the input "line") is returned. 我正在写的实际上是一个解析器,因此一个命令传递到了parse函数(描述了当前状态,向解析器提示了下一步的期望),下一个命令(从输入“ line”派生)是回来。 "context" is free-d at the end of the parse function, which the new command getting returned - which would then be passed back into "parse" with the next "line" of input. 在解析函数的末尾释放了“ context”,返回了新命令-然后将其与下一行“输入”一起传递回“ parse”。

Can anyone suggest anything as to why this might be happening? 谁能提出任何有关为什么可能发生这种情况的建议?

Many thanks. 非常感谢。

When you allocate memory to structure, only a pointer size gets allocated to *desc. 当您将内存分配给结构时,仅将指针大小分配给* desc。 You must allocate memory to the space (array contents) desc points to, as someone already pointed out. 正如已经指出的那样,您必须将内存分配给desc指向的空间(数组内容)。 Purpose of my answer is to show slightly different way of doing that. 我的回答的目的是说明这样做的方式略有不同。 Since having a pointer *desc increases structure size by a word (sizeof pointer), you can safely have a variable length array hack in you structure to reduce structure size. 由于使用指针* desc可以将结构大小增加一个单词(sizeof指针),因此您可以安全地在结构中使用可变长度数组,以减小结构大小。

Here's how your structure should look like, notice that desc[] has been pulled down to the end of structure : 这是您的结构的外观,请注意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;

Now, 1. Allocate memory for command which includes array size also : 现在,1.为还包括数组大小的命令分配内存:

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

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

This hack works only if member is at the end of structure, saves structure size, saves pointer indirection, can be used if array length is structure instance specific. 仅当成员位于结构的末尾,节省结构大小,节省指针间接性时,此技巧才有效。如果数组长度是特定于结构实例的,则可以使用此技巧。

You have to allocate desc and data separately. 您必须分别分配desc和数据。

When you allocate your struct command *cmd, memory is allocated for your pointers of decs and data. 分配struct命令* cmd时,将为decs和数据指针分配内存。 Desc and data have to be malloced separately. Desc和数据必须分别进行malloc。

So allocate your command 所以分配你的命令

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

then allocate memory for data or desc 然后为数据或desc分配内存
example for desc: desc的示例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM