堆和栈上的结构元素

3
所以,我正在创建一个结构,目前需要大量的内存。我希望将来能够减少它,但现在就是这样。因此,如果将其放在堆栈上会导致堆栈溢出,我需要在堆上分配一些元素。是的,我增加了堆栈大小,但在目标平台上,我只有这么多。
在这种情况下,将每个结构元素都分配到堆上是否更好?还是将一部分放在堆栈上,将大型数据放在堆上?例如:
typedef struct my_structure_s{ 

   int bounds[2];
   int num_values;
   int* values;               //needs to be very large

} my_structure_t;

对比:

typedef struct my_structure_s{ 

   int* bounds;
   int* num_values;
   int* values;

} my_structure_t;

我知道“更好”很大程度上是主观的,可能会在这里引起骚动。那么,两个例子的利弊是什么?你通常做什么?为什么?

另外,请原谅_s、_t之类的东西……我知道有些人可能觉得这样做不太合适,但这是遗留代码库的惯例,将被整合到其中。

谢谢大家!


这些结构的大小在几乎所有平台上都是相同的(甚至在一些平台上完全相同)。 - barak manos
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - David C. Rankin
似乎你知道有问题存在,但是在寻求一个万能的解决方法。虽然有时候我们会很幸运,但是用几个指针替换几个整数并不能带来你想象中的那么多好处。在64位系统上,如果不小心处理,可能会占用更多的空间。我建议重新审视递归部分,并看看是否可以将其展开为一个不那么依赖栈的技巧。 - Edwin Buck
2个回答

3

最好将简单成员作为直接值,并只分配数组。使用额外的两个指针只会减慢访问速度,没有任何好处。

如果你使用的是C99或C11,还有另一个选择是使用灵活数组成员(FAM)。

你可以使用以下表示法来定义结构:

typedef struct my_structure_s
{ 
   int bounds[2];
   int num_values;
   int values[];
} my_structure_t;

您需要一次性分配足够的内存空间,包括结构体和N个元素数组 values,可以使用以下代码:

my_structure_t *np = malloc(sizeof(*np) + N * sizeof(np->values[0]));

这意味着你只需要释放一个内存块即可。如果搜索,可以找到“struct hack”的参考资料。这种表示法实际上是“struct hack”的标准形式。

在评论中,讨论继续:

这是一种有趣的方法;然而,我不能保证我会有C99。

如果需要的话,您可以使用代码的 'struct hack' 版本,它看起来像:

typedef struct my_structure_s
{
    int bounds[2];
    int num_values;
    int values[1];
} my_structure_t;

其余代码保持不变。这种方法使用的内存略多一些(比FAM解决方案多4-8个字节),并不严格符合标准,但在C99标准之前广泛使用,因此编译器不太可能使这样的代码无效。

Okay, but how about:

typedef struct my_structure_s
{
    int bounds[2];
    int num_values;
    int values[MAX_SIZE];
} my_structure_t;

And then: my_structure_t *the_structure = malloc(sizeof(my_structure_t));

This will also give me a fixed block size on the heap right? (Except here, my block size will be bigger than it needs to be, in some instances, because I won't always get to MAX_SIZE).

如果平均浪费空间不太多,那么结构体中的固定大小数组仍然更简单。此外,这意味着如果MAX_SIZE不是太大,则可以在堆栈或堆上分配,而FAM方法则需要动态(堆)分配。问题是浪费的空间是否足够成为问题,以及如果MAX_SIZE实际上不够大,该怎么办。否则,这是最简单的方法;我只是假设您已经排除了它。
请注意,建议的每个解决方案都避免了选项2中建议的指向bounds和num_values的指针。

这是一个有趣的方法,但我不能保证我会有C99。例如,当涉及到复数时,C99被规避了 - 即代码库有自己的自制支持。 - The Dude

0

做第一个。它更简单,出错的可能性更小(在第二个中,您必须记住分配和释放更多的东西)

顺便说一句 - 第一个示例不会将num_values放在堆栈上。它将放在您分配结构体、堆栈、堆或静态位置的任何地方


即使进行了更正,你的“答案”的关键是不是只有“它更简单且更少出错”这一点? - David C. Rankin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接