C 堆栈VS堆,这是什么?
所以我开始玩C,到目前为止玩得很开心 然而,有几件事我无法理解 我知道这会在堆栈上结束C 堆栈VS堆,这是什么?,c,pointers,malloc,storage-duration,C,Pointers,Malloc,Storage Duration,所以我开始玩C,到目前为止玩得很开心 然而,有几件事我无法理解 我知道这会在堆栈上结束 int i = 0; 我知道这将在堆上为整数保留空间并返回地址 int *i = malloc(sizeof(int)); 不过。如果我这样做 int i_one = 1, i_two = 2; int *arr = calloc(2, sizeof(int)); arr[0] = i_one; arr[1] = i_two; 当arr在堆上时,i_1和2是堆栈分配的。这是否意味着arr将把i_1和2的
int i = 0;
我知道这将在堆上为整数保留空间并返回地址
int *i = malloc(sizeof(int));
不过。如果我这样做
int i_one = 1, i_two = 2;
int *arr = calloc(2, sizeof(int));
arr[0] = i_one;
arr[1] = i_two;
当arr在堆上时,i_1和2是堆栈分配的。这是否意味着arr将把i_1和2的值复制到堆上,或者只是在堆栈上保存对变量的2个引用。我假设它是alt one的一个变体(如果我没有错的话),只要我退出这个函数,我的堆栈分配的INT就会被释放
总之,在使用calloc创建动态分配的数组时。数组中的条目也需要分配指针/堆吗?在我看来,这是没有意义的,因为这样我就不会创建一个int指针数组了吗?是的,我知道指针的大小和int一样,所以这个例子有点愚蠢,但你明白了
谢谢你你这么说的时候
int *i = malloc(sizeof(int));
这将在堆上结束
事实上,事情并没有那么简单
如果变量
i
是函数中的局部变量,则变量本身的空间将位于“自动存储”中,即堆栈中。但是malloc返回的指针将指向堆。赋值运算符用于将存储在一个对象中的值赋值给另一个对象
所以在这些赋值语句中
arr[0] = i_one;
arr[1] = i_two;
存储在变量i_one
和i_two
中的值被复制到数组元素arr[0]
和arr[1]
占用的内存中。现在,如果您将更改变量i_one
中存储的值,则arr[0]
中存储的值将不会更改
如果要在堆中存储对对象i_one
和i_two
的引用,则应编写
int **arr = calloc(2, sizeof(int *));
arr[0] = &i_one;
arr[1] = &i_two;
现在,您可以使用数组元素arr[0]
以以下方式更改存储在i_one
中的值
*arr[0] = 10;
我通过打印所有相关类型或符号来检查内存映射(最初我使用静态库、动态加载和运行时加载,但可能有点混乱) 我还装箱了两个“堆变量”,并打印它们的地址和包含地址的本地指针 ->->->因此,您可以看到本地指针位于堆栈中,但它们的实际地址位于堆的开头。这就是为什么您可以在堆栈框架之外使用分配的变量-您的本地指针被删除,但地址保留在堆中 这是我的程序输出:
------------------COMMAND-LINE------------------
|*envp---------------------> 140737488347777|
|*argv---------------------> 140737488347751|
|envp---------------------> 140737488346896|
|argv---------------------> 140737488346864|
------------------STACK------------------
|str1---------------------> 140737488346090|
|alloc_second address-----> 140737488346048|
|alloc_first address------> 140737488346040|
|const_local_second ------> 140737488346032|
|const_local_first--------> 140737488346024|
|argc---------------------> 140737488346012|
------------------FUNC-STACK-FRAME------------------
|fun_var_const------------> 140737488345956|
|fun_var_second-----------> 140737488345952|
|fun_var------------------> 140737488345948|
------------------HEAP------------------
------------------------MMS---------------------------------------
|strlen(library func)-----> 140737353401952|
----------------------------------------------------------------
|alloc_second-------------> 4215488|
|alloc_first--------------> 4215456|
------------------BSS------------------
|global_const = 0 --------> 4210812|
|global_int_first---------> 4210808|
|global_double_first------> 4210800|
|static_int_first---------> 4210796|
|global_int_const---------> 4202504|
|------------------DATA------------------
|static_int_second--------> 4210784|
|global_double_second-----> 4210776|
------------------DATA - READ ONLY------------------
|const_static_int_second--> 4204408|
|const_static_int_first---> 4204412|
|string literal-----------> 4202700|
------------------TEXT------------------
|extern function ---------> 4200215|
|function (define after)--> 4200181|
|main --------------------> 4199038|
|static function ---------> 4198870|
-----------------------BOTTOM LINE------------------
并且可以从程序中的每个点访问,因此如果返回
i
,将发送堆地址back@AsafItach是,将复制并返回i
的值,该值是堆分配内存的(第一个字节)位置。堆分配内存的生存期是直到malloc
返回的指针传递到free
为止。正确!我想你对这篇文章很熟悉。。(即使我每次都免费使用malloc工具)@Someprogrammerdude谢谢你的更正,我把它简单化了。是的,malloc将在堆上为int创建空间,我将保留它的地址,我必须跟踪它,并在不再需要时释放它。int和pointer的大小不同(这取决于系统):)int是4字节,而pointer是字大小(在我们的生命周期中是4/8字节:)。真的吗?我认为指针的字节大小总是与整数的字节大小相同,即4或8字节,具体取决于操作系统。我认为在我的情况下,存储实际值会更容易,因为我不需要它们成为指针,一旦创建,我就不需要修改它们(至少不需要修改原始值)。但这意味着当我做arr[0]=I_one;arr[1]=i_-two;那么i_1和i_2的副本就在堆上,对吗?一旦我做了自由(arr)。那么我想这些副本也会从堆中移除?与指针数组的示例不同。@JohanFredin如果要释放指针arr指向的内存,则动态分配数组中存储的值将不可接受。但是i_1和i_2中存储的值将是活动的。