微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在数组中分配内存?

如何解决如何在数组中分配内存?

假设我们有一个数组int arr[size]一个指向整数int *i的指针。我们可以使用*imalloc(sizeof(int) * size)分配一组连续的内存块。但是我的问题是如何在int arr[size]中分配内存。在这种情况下,根据我的猜测分配内存块是由编译器完成的。编译器是否隐式进行malloc()或类似的函数调用?当我们编写类似int arr[] = "You guys are a great help"的东西时,编译器如何完成动态内存分配。

解决方法

有4种不同的情况。

a)全局变量和静态局部变量。为此,通常将数组内置到可执行程序的文件中(通常分为多个部分-一个用于代码,一个用于初始化的只读数据,一个用于初始化的数据,以及一个用于“初始化为零” /未初始化的数据) 。通常,如果数组已初始化(例如int foo[44] = { 1,2,3 };),则将其放入普通的读/写数据部分(.data),如果未初始化(例如int foo[44];),则将其放入将被放在“初始化为零” /未初始化的数据部分(.bss)中以减小文件的大小。在.data节中分配空间与在可执行文件的.text节中为代码分配空间没有太大不同。在这种情况下,无法释放内存。

b)局部变量(在函数内部,例如void foo(void) { int bar[44]; })。在这种情况下,编译器通常会在堆栈上为其创建空间(并且不会“初始化为零”)。如果已对其进行显式初始化,则编译器将使用指令(如果数组较小)或通过在数据节中从隐藏副本中复制数据来生成代码以对其进行初始化(其中,隐藏副本的分配方式与原始方式相同)一直是一个全局变量)。在这种情况下,无法显式释放内存,但是会隐式释放内存(如果/当您从函数返回时)。

c)线程本地存储(例如__thread int foo[])。在这种情况下,编译器通常在线程本地存储中分配空间。如果数组已初始化,它还将在数据节中创建一个隐藏副本(该隐藏副本的分配方式与对全局变量的分配方式相同)。在这种情况下,无法释放内存。

d)动态分配的数组(例如int *myPointer = malloc(sizeof(int) * 44);)。对于这些,编译器不会在任何地方分配空间(运行时库会分配空间)。这是唯一可以显式释放内存(例如free(myPointer);)的情况。

注1:上面的很多内容(我在所有“典型地”使用过的地方)都依赖于实现,并且编译器可能做的非常不同。是因为“不同”对于编译器的输出更有意义,或者是因为编译器可以正确地进行优化。

注2:可悲的是,大多数编译器无法正确优化。在不修改数组的情况下,即使您使用.rodata,也很难使他们使用const部分。对于存在用于初始化的隐藏数组的情况,很难让它们分析内容并查找更复杂的模式(对于(int foo[] = {1,1,1}; }之类的简单模式,它们可能/会做得不好))。如果您有一个像int hugeArray[12345678] = {4,5,6}这样的全局数组,他们将不会将该数组放在.bss节中并对其进行初始化以减小文件大小,即使这样做很简单,等等)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。