Stack VS Heap,这里发生了什么?
Stack VS Heap, what goes where here?
所以我开始玩弄 C,到目前为止玩得很开心。
然而,有几件事我无法理解。
我知道这最终会进入堆栈
int i = 0;
我知道这会为堆上的整数保留 space 和 return 地址
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;
i_one 和两个是堆栈分配的,而 arr 在堆上。这是否意味着 arr 会将 i_one 和两个的值复制到堆上,或者它只是在堆栈上保存 2 个对变量的引用。我假设它是 alt 的一个变体,考虑到(如果我没有记错的话)我的堆栈分配的整数将在我退出此函数后立即被释放。
总而言之,在使用 calloc 创建动态分配的数组时。数组中的条目是否也需要分配指针/堆?在我看来这没有意义,因为那样我就不会创建一个 int 指针数组吗?是的,我知道指针的大小与 int 相同,所以这个例子有点愚蠢,但你明白了。
谢谢
你说
int *i = malloc(sizeof(int));
this will end up on the heap
其实事情并没有那么简单...
如果变量 i
是函数内部的局部变量,那么 变量本身 的 space 将位于“自动存储”中,即堆栈。但是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;
据我所知,我通过打印所有相关类型或符号来检查内存映射(最初我使用静态库、动态加载和 运行-time 加载,但它可能有点混乱)。
我还创建了两个 “堆变量” 并打印它们的地址和包含它们地址的本地指针
->->-> 所以你可以看到本地指针在堆栈中,但它们的 实际 地址在堆的开头。这就是为什么您可以在堆栈框架外使用这个分配的变量 - 您的本地指针被删除但地址保留在堆中。
这是我的程序输出:
------------------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------------------
所以我开始玩弄 C,到目前为止玩得很开心。
然而,有几件事我无法理解。
我知道这最终会进入堆栈
int i = 0;
我知道这会为堆上的整数保留 space 和 return 地址
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;
i_one 和两个是堆栈分配的,而 arr 在堆上。这是否意味着 arr 会将 i_one 和两个的值复制到堆上,或者它只是在堆栈上保存 2 个对变量的引用。我假设它是 alt 的一个变体,考虑到(如果我没有记错的话)我的堆栈分配的整数将在我退出此函数后立即被释放。
总而言之,在使用 calloc 创建动态分配的数组时。数组中的条目是否也需要分配指针/堆?在我看来这没有意义,因为那样我就不会创建一个 int 指针数组吗?是的,我知道指针的大小与 int 相同,所以这个例子有点愚蠢,但你明白了。
谢谢
你说
int *i = malloc(sizeof(int));
this will end up on the heap
其实事情并没有那么简单...
如果变量 i
是函数内部的局部变量,那么 变量本身 的 space 将位于“自动存储”中,即堆栈。但是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;
据我所知,我通过打印所有相关类型或符号来检查内存映射(最初我使用静态库、动态加载和 运行-time 加载,但它可能有点混乱)。
我还创建了两个 “堆变量” 并打印它们的地址和包含它们地址的本地指针
->->-> 所以你可以看到本地指针在堆栈中,但它们的 实际 地址在堆的开头。这就是为什么您可以在堆栈框架外使用这个分配的变量 - 您的本地指针被删除但地址保留在堆中。
这是我的程序输出:
------------------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------------------