学习日志之locate.c的运行及解释

本文通过分析locate.c程序,展示了进程虚拟地址空间的分布,指出全局变量位于数据段,局部变量及指向堆的指针位于栈,malloc分配的内存位于堆,函数位于代码段,而库函数如exit和malloc存在于共享库区域。讨论了堆、栈、共享库和内核虚拟内存的特性。
摘要由CSDN通过智能技术生成

1.locate.c的代码展示
2.运行结果
3.相关解释及知识点

1.locate.c的代码如下

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

static void show_pointer(void *p, char *descr) {
    //    printf("Pointer for %s at %p\n", descr, p);
    printf("%s\t%p\t%lu\n", descr, p, (unsigned long) p);
}

char big_array[1L<<24];    /*  16 MB */
//char huge_array[1L<<31];   /*   2 GB */
char huge_array[1L<<30];/*   1 GB */
int global = 0;

int useless() { return 0; }

int main ()
{
    void *p1, *p2, *p3, *p4;
    int local = 0;
    p1 = malloc(1L << 28);
    p2 = malloc(1L << 8);
    //p3 = malloc(1L << 32);
	p3 = malloc(1L << 16);
    p4 = malloc(1L << 8);

    show_pointer((void *) big_array, "big array");
    show_pointer((void *) huge_array, "huge array");
    show_pointer((void *) &local, "local");
    show_pointer((void *) &global, "global");
    show_pointer((void *) p1, "p1");
    show_pointer((void *) p2, "p2");
    show_pointer((void *) p3, "p3");
    show_pointer((void *) p4, "p4");
    show_pointer((void *) useless, "useless");
    show_pointer((void *) exit, "exit");
    show_pointer((void *) malloc, "malloc");
    return 0;
}

2.运行如下

zoe@zoe-virtual-machine:/mnt/hgfs/Notepad++$ gcc locate.c
zoe@zoe-virtual-machine:/mnt/hgfs/Notepad++$ ./a.out
big array	0x561043850040	94627852255296
huge array	0x561003850040	94626778513472
local	0x7fff383bbb84	140734136826756
global	0x561003850024	94626778513444
p1	0x7f6a4d528010	140094540513296
p2	0x56104680c260	94627902308960
p3	0x56104680c370	94627902309232
p4	0x56104681c380	94627902374784
useless	0x56100364f74d	94626776414029
exit	0x7f6a5d56c120	140094809227552
malloc	0x7f6a5d5c0070	140094809571440

3.详细解释及知识点
由运行结果和进程的虚拟地址空间的分布我们可以推出,三个全局变量big array,huge array和global由上至下位于读/写数据段(data段);主函数里的变量local以及p1到p4位于栈,但运行得到的地址实际上是是p1到p4的值,而不是p1到p4的地址,由于调用了malloc函数,它们所指的内容位于堆中;函数useless位于代码段(text段);库函数exit和malloc位于堆栈之间的共享库。(地址是从下往上增大的)

知识点
下图是示例可执行文件hello.c进程的虚拟地址空间
在这里插入图片描述
程序代码和数据。对所有的进程来说,代码是从同一固定地址开始,紧接着的是和
(全局变量相对应的数据位置。代码和数据区是直接按照可执行目标文件的内容初
始化的,在示例中就是可执行文件hello。
。代码和数据区后紧随着的是运行时堆。代码和数据区在进程一开始运行时就被
指定了大小,与此不同,当调用像malloc和free这样的C标准库函数时,堆可
以在运行时动态地扩展和收缩。
共享库。大约在地址空间的中间部分是一块用来存放像C标准库和数学库这样的共
享库的代码和数据的区域。
。位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一
样,用户栈在程序执行期间可以动态地扩展和收缩。特别地,每次我们调用一个函
数时,栈就会增长;从一个函数返回时,栈就会收缩。
内核虚拟内存。地址空间顶部的区域是为内核保留的。不允许应用程序读写这个区
域的内容或者直接调用内核代码定义的函数。相反,它们必须调用内核来执行这些
操作。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值