Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C:哪一个更好?结构指针的Malloc数组,还是结构数组?_C_Memory_Malloc - Fatal编程技术网

C:哪一个更好?结构指针的Malloc数组,还是结构数组?

C:哪一个更好?结构指针的Malloc数组,还是结构数组?,c,memory,malloc,C,Memory,Malloc,我一直对此很好奇,当在数组内部使用结构时,就内存分配而言,是为数组中的每个条目分配一个新的结构更好,还是在数组中为N个结构分配足够的空间更好 //pointer based: struct myStructure ** tmp = malloc(sizeof(struct myStructure *) * N); tmp[0] = malloc(sizeof(struct myStructure)); tmp[0]->whatever = true; //or structure in

我一直对此很好奇,当在数组内部使用结构时,就内存分配而言,是为数组中的每个条目分配一个新的结构更好,还是在数组中为N个结构分配足够的空间更好

//pointer based:
struct myStructure ** tmp = malloc(sizeof(struct myStructure *) * N);
tmp[0] = malloc(sizeof(struct myStructure));
tmp[0]->whatever = true;

//or structure in the array:
struct myStructure * tmp = malloc(sizeof(struct myStructure) * N);
tmp[0].whatever = true
这两者有什么好处吗?我觉得使用第二种形式是更好的实践,因为您最终会得到更少的小malloc调用,但是可能会有一些情况下您只能使用第一种方法

对此有什么见解吗


谢谢

通常,第二个更好[IMO]-它可能会更便宜[内存和时间],而且更容易维护


然而,在某些情况下,第二种方法可能会失败,而第一种方法会成功。发生这种情况的原因可能是-有足够的内存用于所有结构,但它不在内存中的“一个位置”。

一般来说,我会使用第二种方法,因为如果使用所有插槽,它:

  • 它使用的内存稍少(是指针大小的N倍)
  • 碎片越少,堆越大
  • 避免N次调用
    malloc
    /
    free
    (=>分配/取消分配更快更简单)
  • 在访问每个结构时避免双重间接(非常小的改进)

另一方面,如果您不打算使用阵列的所有插槽(但必须能够根据需要存储许多
struct
s),并且
struct
非常大,那么第一种方法可能很方便,因此节省内存是值得的。此外,如果您需要廉价地更改
结构的顺序,这可能是值得的(尽管您也可以使用第二种方法,通过使用单独的指针数组来实现这一点)。

数组中的结构通常更好;除非你有理由使用另一种形式,否则你应该使用它

从代码正确性的角度来看,您应该处理malloc()失败。如果一个循环中有1000个malloc(),则在错误处理代码中更有可能出现编程错误。类似地,如果您的数据结构更复杂,则更有可能泄漏某些信息。因此,单个malloc()更容易

从分配速度的角度来看,malloc()显然需要时间运行,因此单个malloc()通常会更快

从内存大小的角度来看,malloc()通常在每次分配上都有一些开销。很明显,指针是额外的成本。因此,如果您分配1000个16字节的结构,那么在malloc开销中每个结构可能有16个字节,并且有一个8字节的指针,总共40016字节。执行单个分配只会占用8016字节

从访问速度的角度来看,单个数组可能更快,尤其是当结构较小或按顺序读取结构时。如果这些结构很小,那么其中的几个可以放在一个缓存线中,这样它们就可以作为一个组进行读/写。如果按顺序读取结构,CPU可能会注意到对大阵列的线性访问,并将其预加载到缓存中。如果使用指针数组和单独的分配,那么内存布局更随机,这两种优化都不起作用。此外,由于您正在访问更多的数据(指针),您的算法将很快从数据缓存中消失


从内存碎片的角度来看,这取决于。如果您有足够大的结构(占总RAM的很大一部分),那么您可能会遇到这样的情况:没有足够的连续可用内存来分配单个大数组,但有足够的内存来分配指针数组和单个结构。(例如,如果操作系统上的32位程序将内存限制为2GB,而内存分配器在内存的一半分配了其他内容,则您不能进行一次1.5GB的分配,但可以进行15次100MB的分配)。这种情况很少见,因为人们通常不会处理那么大的数据。

目前有三个非常好的答案可以解释为什么应该使用第二种方法,所以我不会重复他们的答案。我想说的是,第一种方法有几个好处:

  • 第一个阵列更易于根据其在系统中的实际需要进行扩展和收缩。增加第一个指针数组非常容易——每个元素总共有四到八个字节长,因此将数组大小增加一倍不会花费太多

    实际结构的第二个数组可能要大得多(按
    struct foo的大小
    乘以元素的数量),如果
    realloc(3)
    没有足够的可用空间来处理,则稍微增加数组可能会耗尽内存

  • 第一个数组使您能够通过“句柄”引用系统中的对象,并根据需要重新安排它们的内存。您可以按页面大小分配底层对象,并将对象重新压缩到几乎满的平板上——这样您就可以将页面返回到操作系统供以后使用。系统中的其他对象必须经过另一个间接层才能到达被引用的对象,但是当您移动对象时,这些客户机对象(“referent”?)不需要更新其指针

  • 第一个数组中对象的生存期是“解耦的”——其中一些对象可能会生存很长时间,而另一些对象可能只生存几毫秒。在第二个数组中,整个数组具有相同的生存期。您可以向第二个数组中添加额外的数据结构,以管理哪些对象是活动的,哪些是非活动的,或者在结构中添加新字段以指示哪些是活动的,哪些是非活动的,但这两种方法都需要更多的工作。对于第一个数组,如果指针是非空的,则对象是活动的

这两种方法都有各自的特点