关闭

C与虚拟内存

413人阅读 评论(0) 收藏 举报

一、C和C++的区别:C和C++的主要差别,C语言缺少对bool值,引用,模板,命名空间,面向对象,异常特性的支持。C比C++更适合底层开发,因为C能够提供稳定的ABI(Application Binary  Interface)接口。ABI不同于API ,API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译 ,然而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。ABI掩盖了各种细节,例如:调用约定控制着函数的参数如何传送以及如何接受返回值;系统调用的编码和一个应用如何向操作系统进行系统调用;以及在一个完整的操作系统ABI中,对象文件的二进制格式、程序库等等。

C的函数调用:

#include<stdio.h>

int add(int a,int b)

{

return a+b;

}

main()

{

int (*fun)(int )=(int (* )(int )) add;

fun f=f(20);

printf("%d\n",r);

}

该程序尽管实参和形参不匹配,但是依然能够正常运行。

下面研究函数调用的本质:

函数执行的时候有自己的临时栈

函数的参数就在临时栈中,如果函数传递实参,则用来初始化临时的参数变量,如上函数,即使传递三个参数不会报错,程序会忽略第三个参数

#include<stdio.h>

int add(int *a,int *b)

{

return (*a)+(*b);

}

main()

{

int a=20;

int b=30;

int r=add(&a,&b);  \\传递指针变量,地址值

printf("%d\n",r);


int (*fun)(int )=(int (* )(int )) add;

fun f=f(20);

printf("%d\n",r);

}

二种函数结果返回方式,直接返回、通过函数的参数返回。

通过参数来返回值,(告诉必须是指针)

指针指向的区域必须事先分配,在函数中操作该区域,函数返回后,该区别不会销毁


函数指定三种调用方式,__stdcall _cdecl _fastcall,这些方式直接影响编译器。

(linux中可通过gcc test.c  -s与cat test.s查看对应的汇编代码)

1.决定我们函数栈压栈的顺序,函数参数从右向左压栈

2.决定函数栈清空的方式

3.决定了函数的名字转换方式

stdcall调用者清空

cdecl有专用参数来标识清空方式,统一清空

fastcall自己在返回前空间

几种类型的指针

far near huge指针

near 16

far 32位

huge 综合


二.虚拟内存

  先看一个程序:

#include<stdio.h>

#include<stdlib.h>

main()

{

int *p=malloc(0);

*p=9999;

printf("%d\n",*p);

}

能够正常输出9999

一个程序程序不能访问另一个程序指向的空间,

每个程序的开始地址都是0X80084000,这个不是物理地址,是每个程序的逻辑地址,也即虚拟内存。

逻辑地址仅仅是编号,统带使用int 4字节整数表示,2的32次方,即4G的空间。每个程序提供4G的访问能力,逻辑地址与物理地址关联才有意义,这个过程称为内存映射。strace main跟踪程序执行,查以查看映射。虚拟内存的提出,目的在于不允许程序直接文章物理内存,提高程序的可靠性,有助于系统的稳定。

虚拟与物理 地址在映射的时候,有一个基本单位 4K 1000即内存页,

段错误:无效访问,访问了无法映射的物理地址。

合法访问:比如malloc分配的空间之外的空间,可以访问,但访问非法。

虚拟内存的分配

栈:编译器自动生成代码维护

堆:地址是否映射,映射的空间是否被管理

brk/sbrk 内存映射函数

帮助手册的使用,man      节      关键词

节为1-8     1:linux系统指令,shell命令

2:系统函数 查看brk/sbrk函数说明

                                3:标准C函数的帮助文档 

7:系统的编程帮助  man 7 tcp   常用的节

分配与释放内存:

int brk(void *end)  //分配空间,释放空间  与malloc 区别

1使用sbrk分配空间

2.使用sbrk得到没有映射的虚拟地址,得到一大块未分配的地址的首地址

3使用brk分配空间

4使用brk释放空间

void *sbrk(int size); //返回空间地址  如果是第一次运行,则返回没有映射的空闲空间首地址,

同时产生一个数据结构,指向该空间

sbrk与brk后台系统维护一个指针,指针默认是NULL,第一次调用sbrk,我们判定指针是否是0,是则得到大块空闲空间首地址来初始化指针

同时指针+参数size,否,则返回指针并把指针位置+size(参数

malloc 用brk来实现

作业:写一个程序查找1-10000之间所有的素数,并且存放到缓冲,然后打印。用数组实现太耗空间,缓冲用Sbrk/brk实现。

总结:

系统操作内存有哪下几种方式:智能指针、STL、new、malloc、brk/sbrk,依次上高级到低级。

int brk(void *)

void *sbrk(int )

如果成功brk返回0 sbrk返回指针

失败 brk返回-1 sbrk返回 (void *) -1

unix函数如果错误,修改一个内部errno

打印错误方法:

1.peror 打印详细信息

2.printf("memory:%m\n"):

3.printf("::%s\n",strerror(error));

补充知识,inux中重要的函数:子符串函数 string.h cstring、内存管理函数 malloc memset mamcmp memcpy bzero、错误处理函数、标准IO函数、时间函数、类型转换函数

作业:打印1-10000之间所有孪生素数

 打印当前的日期时间:格式

0000年00月00 00:00:00



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:9216次
    • 积分:233
    • 等级:
    • 排名:千里之外
    • 原创:13篇
    • 转载:7篇
    • 译文:0篇
    • 评论:0条
    文章分类