关于内存进程和函数共享的问题
Question about memory process and function sharing
1)为什么我们不能在 c 中使用虚拟地址而不是变量,例如而不是写 int x ;我们可以创建一个指向堆栈中第一个地址的指针,如 int *x=1; ,如果我们喜欢声明第二个变量。
我们使用了类似 int *y=2 的下一个地址。
或者我们可以使用堆栈中的最后一个地址作为动态数组而不是使用堆。
2)
函数是否共享相同的堆栈,如果它们共享,为什么我们不能在函数外部访问函数的局部变量。
我认为他们没有,但我看不到功能上下文是如何改变的,因为他们不同时朗姆酒
3)
long类型是否在栈中占用两个地址,每个地址都是4字节?
如果是这样,是不是改变了数学运算符
- Why cant we use virtual address in c instead variable for example instead writing int x ; we may create a pointer to the first address in the stack like that int *x=1; ,and if we liked to declare second variable . we used the next address like that int *y=2. or we can use the last address valued in the stack as dynamic array instead of using the heap.
好吧,你可以使用虚拟地址而不是变量,比如 int* a=(int*)0x8000B
,这只会在没有 OS 的环境中工作,比如在引导加载程序中,因为地址,程序被加载通常是不同,如果你使用 OS.
您可以 int* x=(int*)1
、int* x=(int*)5
,但它可能会在某些架构上崩溃,因为这些架构未与 sizeof(int)
(通常为 2 或 4 个字节)的倍数对齐。
此外,如果您编写的程序没有 OS,它仅适用于此类地址,因为大多数 OS 保留前几页。 ==> 你不能用它们做任何事情。
we can use the last address valued in the stack as dynamic array instead of using the heap.
对不起,我真的不明白你的意思。堆栈不是动态数组,它只是一个内存地址和一些空闲 space(例如“普通”PC 上的 2MB 或嵌入式设备中只有几百个字节)。
- Does function share the same stack and if they do why can't we access local variable of function out side the function. i think they don't but I cant see how the function context changed because they don't rum at the same time
是的,他们共享同一个堆栈。
您可以使用一些技巧来访问它们,但这些都是非常邪恶的。
假设你有一个函数 _start
。它以一个空堆栈开始(rbp=0x1000,rsp=0x1000)。然后在栈上分配一些局部变量。 (rbp=0x1000,rsp=0xff0)。之后,它调用 main
。
跳转到的地址存储在堆栈中,并更新基指针。
现在栈指针和栈基指针有这些地址:rbp=0xfe8,rsp=0xfe8
因为 SysV-ABI 要求 16 字节对齐,所以您必须再次减去 8 个字节。
rbp=0xfe8,rsp=0xfe0。
现在您可以使用 movq 22(%rsp),%rax
开始访问一些局部变量。您现在可能拥有本地的一部分或整个本地。
每次对源代码或编译器标志进行微小更改时,此技巧都会失败。
- Does the long type takes two address in the stack that each one of them is 4 bytes?
不,long 类型在堆栈上占用 sizeof(long)
个字节。地址具有固定大小。四个(32 位系统)或八个(64 位系统)。
for example instead writing int x ; we may create a pointer to the first address in the stack
因为C比汇编更高级。 C 语言不知道也不关心栈的存在。与汇编程序相比,高级语言的主要好处之一是摆脱了手动堆栈管理。因为汇编程序中最常见的错误之一是忘记 push/pop 堆栈中的某些内容 - 你永远不会遇到像 C 中那样的错误,因为处理堆栈的指令是由编译器生成的。
所以 C 程序员不想手动处理堆栈,主要是因为这样做很痛苦。您描述的伪代码非常接近汇编程序的工作方式,其中指令通常与堆栈指针相关。 “读取内存位置 SP+3”等
or we can use the last address valued in the stack as dynamic array instead of using the heap
不,因为堆栈的大小有限,并且作为 ABI 调用约定的一部分还用于存储寄存器和 return 地址。堆是一个更高层的概念,其中可以存储大量数据并与同一进程内的所有内容共享,或者甚至与其他进程共享,具体取决于系统。
编程老师把事情简单化了很多,说内存有两种形式:栈和堆,这是个通病。然后学生们对这两者着迷并开始做出各种疯狂的结论。实际上,主流计算机有 .stack
、.data
、.bss
、.heap
、.rodata
、.text
和各种其他段(通常是不同风格的提到的那些)。变量可以存储在这些段中的任何一个中。例如,它们最终会与 .text
中的程序代码混合,以防它们被优化为寄存器访问而不是存储在堆栈中。
Does function share the same stack
如果你的意思是如果不同函数内的局部变量共享同一个堆栈,那么在正常情况下是的,假设 single-thread、single-process.
Does the long type takes two address in the stack that each one of them is 4 bytes?
long
的大小未按标准指定,可能为 4 或 8 个字节。它们的分配位置取决于上下文。
- Why cant we use virtual address in c instead variable for example instead writing int x ; we may create a pointer to the first address in the stack like that int *x=1; ,and if we liked to declare second variable . we used the next address like that int *y=2. or we can use the last address valued in the stack as dynamic array instead of using the heap.
在 C 中,如果您需要堆栈存储,您要么声明局部变量,要么使用 alloca
分配堆栈内存。例如,我们可以这样做:
#include <iostream>
int main()
{
typedef struct {
int x;
int y;
} myStruct;
myStruct *p = (myStruct *) alloca ( sizeof myStruct );
p -> x = 100;
p -> y = 200;
p -> x += 100;
}
这为我们提供了存储 x
和 y
,我们可以通过 p->x
和 p->y
.
引用它们
然而,使用局部变量要简单得多,并且需要编译器做更少的工作来弄清楚局部变量甚至可能不需要堆栈存储,它们可以简单地存在于 CPU 寄存器中。
- Does function share the same stack and if they do why can't we access local variable of function out side the function. i think they don't but I cant see how the function context changed because they don't rum at the same time
对于每个线程,都有一个动态调用链,线程中的所有函数都共享同一个局部变量堆栈。更具体地说,函数调用在概念上激活堆栈中的帧或记录。
确实有一些语言允许 non-local 引用——引用在它们自己的局部变量之外,但不是全局变量。这些语言通常支持嵌套在函数中的函数。特别是第一个 class 函数(函数指针),这些通常被称为闭包。在像 Pascal 这样的旧语言中,non-local 变量的使用提供了一个穷人的面向对象编程能力。支持其中任何一个都需要相当多的幕后机制、框架指针和反向链接等。我认为 C 编程语言选择不实现嵌套函数是为了简化目的。可以用堆对象代替,堆对象更通用(但需要手动分配和释放)。
- Does the long type takes two address in the stack that each one of them is 4 bytes?
可能,是的。
1)为什么我们不能在 c 中使用虚拟地址而不是变量,例如而不是写 int x ;我们可以创建一个指向堆栈中第一个地址的指针,如 int *x=1; ,如果我们喜欢声明第二个变量。 我们使用了类似 int *y=2 的下一个地址。 或者我们可以使用堆栈中的最后一个地址作为动态数组而不是使用堆。
2) 函数是否共享相同的堆栈,如果它们共享,为什么我们不能在函数外部访问函数的局部变量。 我认为他们没有,但我看不到功能上下文是如何改变的,因为他们不同时朗姆酒
3) long类型是否在栈中占用两个地址,每个地址都是4字节?
如果是这样,是不是改变了数学运算符
- Why cant we use virtual address in c instead variable for example instead writing int x ; we may create a pointer to the first address in the stack like that int *x=1; ,and if we liked to declare second variable . we used the next address like that int *y=2. or we can use the last address valued in the stack as dynamic array instead of using the heap.
好吧,你可以使用虚拟地址而不是变量,比如 int* a=(int*)0x8000B
,这只会在没有 OS 的环境中工作,比如在引导加载程序中,因为地址,程序被加载通常是不同,如果你使用 OS.
您可以 int* x=(int*)1
、int* x=(int*)5
,但它可能会在某些架构上崩溃,因为这些架构未与 sizeof(int)
(通常为 2 或 4 个字节)的倍数对齐。
此外,如果您编写的程序没有 OS,它仅适用于此类地址,因为大多数 OS 保留前几页。 ==> 你不能用它们做任何事情。
we can use the last address valued in the stack as dynamic array instead of using the heap.
对不起,我真的不明白你的意思。堆栈不是动态数组,它只是一个内存地址和一些空闲 space(例如“普通”PC 上的 2MB 或嵌入式设备中只有几百个字节)。
- Does function share the same stack and if they do why can't we access local variable of function out side the function. i think they don't but I cant see how the function context changed because they don't rum at the same time
是的,他们共享同一个堆栈。
您可以使用一些技巧来访问它们,但这些都是非常邪恶的。
假设你有一个函数 _start
。它以一个空堆栈开始(rbp=0x1000,rsp=0x1000)。然后在栈上分配一些局部变量。 (rbp=0x1000,rsp=0xff0)。之后,它调用 main
。
跳转到的地址存储在堆栈中,并更新基指针。
现在栈指针和栈基指针有这些地址:rbp=0xfe8,rsp=0xfe8
因为 SysV-ABI 要求 16 字节对齐,所以您必须再次减去 8 个字节。
rbp=0xfe8,rsp=0xfe0。
现在您可以使用 movq 22(%rsp),%rax
开始访问一些局部变量。您现在可能拥有本地的一部分或整个本地。
每次对源代码或编译器标志进行微小更改时,此技巧都会失败。
- Does the long type takes two address in the stack that each one of them is 4 bytes?
不,long 类型在堆栈上占用 sizeof(long)
个字节。地址具有固定大小。四个(32 位系统)或八个(64 位系统)。
for example instead writing int x ; we may create a pointer to the first address in the stack
因为C比汇编更高级。 C 语言不知道也不关心栈的存在。与汇编程序相比,高级语言的主要好处之一是摆脱了手动堆栈管理。因为汇编程序中最常见的错误之一是忘记 push/pop 堆栈中的某些内容 - 你永远不会遇到像 C 中那样的错误,因为处理堆栈的指令是由编译器生成的。
所以 C 程序员不想手动处理堆栈,主要是因为这样做很痛苦。您描述的伪代码非常接近汇编程序的工作方式,其中指令通常与堆栈指针相关。 “读取内存位置 SP+3”等
or we can use the last address valued in the stack as dynamic array instead of using the heap
不,因为堆栈的大小有限,并且作为 ABI 调用约定的一部分还用于存储寄存器和 return 地址。堆是一个更高层的概念,其中可以存储大量数据并与同一进程内的所有内容共享,或者甚至与其他进程共享,具体取决于系统。
编程老师把事情简单化了很多,说内存有两种形式:栈和堆,这是个通病。然后学生们对这两者着迷并开始做出各种疯狂的结论。实际上,主流计算机有 .stack
、.data
、.bss
、.heap
、.rodata
、.text
和各种其他段(通常是不同风格的提到的那些)。变量可以存储在这些段中的任何一个中。例如,它们最终会与 .text
中的程序代码混合,以防它们被优化为寄存器访问而不是存储在堆栈中。
Does function share the same stack
如果你的意思是如果不同函数内的局部变量共享同一个堆栈,那么在正常情况下是的,假设 single-thread、single-process.
Does the long type takes two address in the stack that each one of them is 4 bytes?
long
的大小未按标准指定,可能为 4 或 8 个字节。它们的分配位置取决于上下文。
- Why cant we use virtual address in c instead variable for example instead writing int x ; we may create a pointer to the first address in the stack like that int *x=1; ,and if we liked to declare second variable . we used the next address like that int *y=2. or we can use the last address valued in the stack as dynamic array instead of using the heap.
在 C 中,如果您需要堆栈存储,您要么声明局部变量,要么使用 alloca
分配堆栈内存。例如,我们可以这样做:
#include <iostream>
int main()
{
typedef struct {
int x;
int y;
} myStruct;
myStruct *p = (myStruct *) alloca ( sizeof myStruct );
p -> x = 100;
p -> y = 200;
p -> x += 100;
}
这为我们提供了存储 x
和 y
,我们可以通过 p->x
和 p->y
.
然而,使用局部变量要简单得多,并且需要编译器做更少的工作来弄清楚局部变量甚至可能不需要堆栈存储,它们可以简单地存在于 CPU 寄存器中。
- Does function share the same stack and if they do why can't we access local variable of function out side the function. i think they don't but I cant see how the function context changed because they don't rum at the same time
对于每个线程,都有一个动态调用链,线程中的所有函数都共享同一个局部变量堆栈。更具体地说,函数调用在概念上激活堆栈中的帧或记录。
确实有一些语言允许 non-local 引用——引用在它们自己的局部变量之外,但不是全局变量。这些语言通常支持嵌套在函数中的函数。特别是第一个 class 函数(函数指针),这些通常被称为闭包。在像 Pascal 这样的旧语言中,non-local 变量的使用提供了一个穷人的面向对象编程能力。支持其中任何一个都需要相当多的幕后机制、框架指针和反向链接等。我认为 C 编程语言选择不实现嵌套函数是为了简化目的。可以用堆对象代替,堆对象更通用(但需要手动分配和释放)。
- Does the long type takes two address in the stack that each one of them is 4 bytes?
可能,是的。