为什么malloc需要用于C中的动态内存分配?

aurhwmvo  于 12个月前  发布在  其他
关注(0)|答案(6)|浏览(88)

我一直在阅读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可能是动态内存分配的更好解决方案。

oknwwptz

oknwwptz1#

查找stackheap的概念;不同类型的内存有很多微妙之处。函数内部的局部变量存在于stack中,并且只存在于函数内部。
在你的例子中,int_array只在定义它的函数执行还没有结束时存在,你不能在函数之间传递它。你不能返回int_array并期望它工作。
malloc()用于当你想创建一个存在于heap上的内存块时。malloc返回一个指向这个内存的指针。这个指针可以作为一个变量(例如return ed)从函数中传递,并且可以在你的程序中的任何地方使用来访问你分配的内存块,直到你free()它。

示例:

C

int main(int argc, char **argv){
    int length = 10; 
    int *built_array = make_array(length); //malloc memory and pass heap pointer
    int *array = make_array_wrong(length); //will not work. Array in function was in stack and no longer exists when function has returned.

    built_array[3] = 5; //ok
    array[3] = 5; //bad 

    free(built_array) 

    return 0;  
 }

int *make_array(int length){
    int *my_pointer = malloc( length * sizeof int);
    //do some error checking for real implementation 
    return my_pointer; 
}

int *make_array_wrong(int length){
    int array[length]; 
    return array; 
 }

字符串
'''

**注意:**有很多方法可以避免使用malloc,例如在调用者中预先分配足够的内存等。建议用于嵌入式和安全关键型程序,确保您永远不会耗尽内存。

cvxl0en2

cvxl0en22#

声明局部变量会从堆栈中占用内存。
1.一旦函数返回,该内存将被释放。
1.堆栈内存是有限的,并且用于 * 所有 * 局部变量,以及函数返回地址。如果你分配大量内存,你会遇到问题。只将它用于少量内存。

nvbavucw

nvbavucw3#

仅仅因为一些东西看起来更漂亮并不能使它成为一个更好的选择。
VLA有一长串的问题,尤其是它们不能充分替代堆分配的内存。
主要的--也是最重要的--原因是VLA不是 * 持久的 * 动态数据。也就是说,一旦你的函数终止,数据就会被回收(它存在于堆栈上的所有地方!),这意味着任何其他仍然挂在它上面的代码都是SOL。
你的示例代码不会遇到这个问题,因为你没有在本地上下文之外使用它。继续尝试使用VLA构建一个二叉树,然后添加一个节点,然后创建一个新树,并尝试打印它们。
下一个问题是堆栈不是分配大量动态数据的合适位置--它是用于函数帧的,函数帧的开始空间有限。全局内存池OTOH是专门为这种用途设计和优化的。
提出问题并试图理解事物是很好的。只是要小心,你不相信自己比很多很多人更聪明,他们用现在近80年的经验来设计和实现系统,这些系统实际上运行着已知的宇宙。这样一个明显的缺陷会在很久很久以前就被发现,并在我们出生之前被消除。
VLA有自己的位置,但它是,唉,小。

k4ymrczo

k4ymrczo4#

当你的函数代码中有以下内容时:

int int_arr[n];

字符串
这意味着你在函数栈上分配了空间,一旦函数返回,这个栈将不复存在。
想象一个需要向调用者返回数据结构的用例,例如:

Car* create_car(string model, string make)
{
    Car* new_car = malloc(sizeof(*car));
    ...
    return new_car;

}


现在,一旦函数完成,你仍然会有你的汽车对象,因为它是在堆上分配的。

vaj7vani

vaj7vani5#

int int_arr[n]分配的内存仅保留到例程执行结束(当它返回或以其他方式终止时,如setjmp)。这意味着你不能以一种顺序分配东西,并以另一种顺序释放它们。你不能分配一个临时工作缓冲区,在计算某些数据时使用它,然后为结果分配另一个缓冲区,然后释放临时工作缓冲区。要释放工作缓冲区,你必须从函数返回,然后结果缓冲区将被释放到。
使用自动分配,你不能从文件中读取,为从文件中读取的每个内容分配记录,然后无序删除一些记录。你根本无法动态控制分配的内存;自动分配被强制为严格的后进先出(LIFO)顺序。
你不能编写分配内存、初始化内存和/或进行其他计算的子例程,并将分配的内存返回给它们的调用者。
(Some人们可能还指出,通常用于自动对象的堆栈内存通常限制在1-8 mebibytes,而用于动态分配的内存通常要大得多。然而,这是为通常使用而选择的设置的人工产物,可以改变;它不是自动与动态分配的本质所固有的。)

3ks5zfa0

3ks5zfa06#

如果分配的内存很小,只在函数内部使用,malloc确实是不必要的。如果内存量特别大(通常是MB以上),上面的例子可能会导致堆栈溢出。如果函数返回后内存还在使用,则需要malloc或者全局变量(静态分配)。
请注意,某些编译器可能不支持上述通过局部变量的动态分配。

相关问题