我一直在阅读malloc是用于动态内存分配。但如果下面的代码工作.
int main(void) {
int i, n;
printf("Enter the number of integers: ");
scanf("%d", &n);
// Dynamic allocation of memory?
int int_arr[n];
// Testing
for (int i = 0; i < n; i++) {
int_arr[i] = i * 10;
}
for (int i = 0; i < n; i++) {
printf("%d ", int_arr[i]);
}
printf("\n");
}
字符串
. malloc的意义是什么?上面的代码不就是一种更容易阅读的动态分配内存的方法吗?
我读到另一个Stack Overflow的回答,如果某种标志被设置为“pedantic”,那么上面的代码将产生编译错误。但这并不能真正解释为什么 * malloc可能是动态内存分配的更好解决方案。
6条答案
按热度按时间oknwwptz1#
查找
stack
和heap
的概念;不同类型的内存有很多微妙之处。函数内部的局部变量存在于stack
中,并且只存在于函数内部。在你的例子中,
int_array
只在定义它的函数执行还没有结束时存在,你不能在函数之间传递它。你不能返回int_array
并期望它工作。malloc()
用于当你想创建一个存在于heap上的内存块时。malloc
返回一个指向这个内存的指针。这个指针可以作为一个变量(例如return
ed)从函数中传递,并且可以在你的程序中的任何地方使用来访问你分配的内存块,直到你free()
它。示例:
C
字符串
'''
**注意:**有很多方法可以避免使用
malloc
,例如在调用者中预先分配足够的内存等。建议用于嵌入式和安全关键型程序,确保您永远不会耗尽内存。cvxl0en22#
声明局部变量会从堆栈中占用内存。
1.一旦函数返回,该内存将被释放。
1.堆栈内存是有限的,并且用于 * 所有 * 局部变量,以及函数返回地址。如果你分配大量内存,你会遇到问题。只将它用于少量内存。
nvbavucw3#
仅仅因为一些东西看起来更漂亮并不能使它成为一个更好的选择。
VLA有一长串的问题,尤其是它们不能充分替代堆分配的内存。
主要的--也是最重要的--原因是VLA不是 * 持久的 * 动态数据。也就是说,一旦你的函数终止,数据就会被回收(它存在于堆栈上的所有地方!),这意味着任何其他仍然挂在它上面的代码都是SOL。
你的示例代码不会遇到这个问题,因为你没有在本地上下文之外使用它。继续尝试使用VLA构建一个二叉树,然后添加一个节点,然后创建一个新树,并尝试打印它们。
下一个问题是堆栈不是分配大量动态数据的合适位置--它是用于函数帧的,函数帧的开始空间有限。全局内存池OTOH是专门为这种用途设计和优化的。
提出问题并试图理解事物是很好的。只是要小心,你不相信自己比很多很多人更聪明,他们用现在近80年的经验来设计和实现系统,这些系统实际上运行着已知的宇宙。这样一个明显的缺陷会在很久很久以前就被发现,并在我们出生之前被消除。
VLA有自己的位置,但它是,唉,小。
k4ymrczo4#
当你的函数代码中有以下内容时:
字符串
这意味着你在函数栈上分配了空间,一旦函数返回,这个栈将不复存在。
想象一个需要向调用者返回数据结构的用例,例如:
型
现在,一旦函数完成,你仍然会有你的汽车对象,因为它是在堆上分配的。
vaj7vani5#
int int_arr[n]
分配的内存仅保留到例程执行结束(当它返回或以其他方式终止时,如setjmp
)。这意味着你不能以一种顺序分配东西,并以另一种顺序释放它们。你不能分配一个临时工作缓冲区,在计算某些数据时使用它,然后为结果分配另一个缓冲区,然后释放临时工作缓冲区。要释放工作缓冲区,你必须从函数返回,然后结果缓冲区将被释放到。使用自动分配,你不能从文件中读取,为从文件中读取的每个内容分配记录,然后无序删除一些记录。你根本无法动态控制分配的内存;自动分配被强制为严格的后进先出(LIFO)顺序。
你不能编写分配内存、初始化内存和/或进行其他计算的子例程,并将分配的内存返回给它们的调用者。
(Some人们可能还指出,通常用于自动对象的堆栈内存通常限制在1-8 mebibytes,而用于动态分配的内存通常要大得多。然而,这是为通常使用而选择的设置的人工产物,可以改变;它不是自动与动态分配的本质所固有的。)
3ks5zfa06#
如果分配的内存很小,只在函数内部使用,malloc确实是不必要的。如果内存量特别大(通常是MB以上),上面的例子可能会导致堆栈溢出。如果函数返回后内存还在使用,则需要malloc或者全局变量(静态分配)。
请注意,某些编译器可能不支持上述通过局部变量的动态分配。