笔记:程序内存管理 .bss .data .rodata .text stack heap
1.未初始化的全局变量(.bss段)
bss段用来存放 没有被初始化 和 已经被初始化为0 的全局变量。如下例代码:
#include<stdio.h> int bss_array[1024*1024];
int main(int argc, char *argv[])
{
return 0;
}
编译并查看:
$ gcc -g mainbss.c -o mainbss
$ ls -l mainbss
-rwxrwxr-x. 1 hy hy 8330 Apr 22 19:33 mainbss
$ objdump -h mainbss |grep bss
mainbss: file format elf32-i386
24 .bss 00400020 0804a020 0804a020 00001018 2**5
$ size mainbss
text data bss dec hex filename
1055 272 4194336 4195663 40054f mainbss
全局变量bss_array的大小为4MB = 1024*1024*sizeof(int) Byte = 4194304 Byte。 通过size 查看可知数据被存在了 bss 段
而 可执行文件mainbss 有8KB左右,命令 ls -l mainbss 查看得知。可知,bss类型的全局变量只占用 运行时的内存空间,而不占用可执行文件自身的文件空间。
2017-11-24
今天再读此书时,联想到 OR1200 编译过程中的 RAM 和 链接脚本,产生一个问题。在 OR 仿真验证中,我的RAM只有8KB的空间,若我有一个定义上诉数组,可执行文件本身不大,但是运行时需要占用4M的空间。那程序岂不是会崩溃? 带着这个问题。在OR的验证程序中做了测试。
个人结论: 若在运行时这个空间不足的问题,编译器会帮忙检查的。这些是数据,若是在运行时的 堆和栈 不足,这点编译器没法检查。
#include"uart.h"
volatile unsigned long timestamp = ;
#define DRAM_MEM_SIZE (0x200)
#define DRAM_ADDR_START (0x1FFF-DRAM_MEM_SIZE+1)
#define DRAM_ADDR_END (0x1FFF) #define Struct_Section __attribute__((unused, section(".stdata_mem_type"), \
aligned())) typedef unsigned int u32;
typedef signed int s32; char txbuf[]={0x01,0x03,0x07,0x0f,0x10,0x30,0x70};
char testbss;
char testdata=;
typedef struct {
char ch[];
unsigned int addrinit;
unsigned int len;
}STDATA_MEM_TYPE;
STDATA_MEM_TYPE arry_dynamic Struct_Section;
int t_array[*]={}; int main(void)
{
//省略
}
编译报错如下, .bss 段不够用:
openrisc@openrisc-VirtualBox:~/mc-or-lngit/or_bootsim_shpy/hyor_ramboot$ make
or32-elf-gcc -c reset.S -o reset.o
or32-elf-gcc -c main.c -o main.o
or32-elf-gcc -c uart.c -o uart.o
or32-elf-ld reset.o main.o uart.o -T ram.ld -o hyor_ramboot.or32
or32-elf-ld: hyor_ramboot.or32 section `.bss' will not fit in region `ram'
or32-elf-ld: region `ram' overflowed by 4192276 bytes
make: *** [hyor_ramboot.or32] Error
2. 已被初始化为非零的全局变量(.data段)
data段用来存放已经被初始化为非零的全局变量。如下代码,只将矩阵的第一个元素初试化为1:
#include<stdio.h> int data_array[1024*1024]={1};
int main(int argc, char *argv[])
{
return 0;
}
编译查看
[hy@localhost memcfg]$ gcc -g maindata.c -o maindata
[hy@localhost memcfg]$ ls -l maindata
-rwxrwxr-x. 1 hy hy 4202682 Apr 22 19:48 maindata
[hy@localhost memcfg]$ objdump -h maindata |grep \\.data
23 .data 00400020 0804a020 0804a020 00001020 2**5
[hy@localhost memcfg]$ size maindata
text data bss dec hex filename
1055 4194604 4 4195663 40054f maindata
而 可执行文件maindata 有4MB左右。通过size 查看可知数据被存在了 data 段
可知,data类型的全局变量既占用运行时的内存空间,也占用可执行文件自身的文件空间。
3.常量数据(.rodata段)
1)rodata用来存放常量数据。 ro: read only
2)字符串会被编译器自动放在rodata中,加 const 关键字的常量数据会被放在 rodata 中
3)在有的嵌入式系统中, rodata放在 ROM(或 NOR Flash)里,运行时直接读取,不须加载到RAM内存中。
所以,在嵌入式开发中,常将已知的常量系数,表格数据等造表加以 const 关键字。存在ROM中,避免占用RAM空间。
4.代码(.text段)
text段存放代码(如:函数)和部分整数常量(应该指的是一些立即数),这个段是可执行的。
5.栈(stack)
1)stack 存放函数的局部变量和函数参数
2)被调用函数的参数和返回值 被存储到当前程序的栈区,之后被调用函数再为自身的自动变量和临时变量在栈区上分配空间
3)函数返回时,栈区的数据会被释放掉,先入后出(FILO)的顺序。
6.堆(heap)
heap用来动态分配内存,由程序自身决定开辟和释放。
6.1 malloc/free
#include<stdio.h>
#include<stdlib.h> int main(int argc, char *argv[])
{
int *p = (int *)malloc(10*1);
// p= (int *)malloc(10*1);
if(p==NULL) {
printf("malloc p err\n");
return -1;
}
free(p);
printf("p = %4x\n",p);
p = NULL;
printf("p = %4x\n",p);
return 0;
}
程序运行结果:
[hy@localhost memcfg]$ gcc maindata.c
[hy@localhost memcfg]$ ./a.out
p = 9cf4008
p = 0
1)开辟了空间,就要适时的释放。释放时,指针应指向开辟时的内存空间,所以在使用指针时,要注意不要修改了其地址,或者将开辟时的起始地址保存起来。
2)对指针free后,其地址不一定就为NULL。如代码中的 p,在 free(p)后,printf("p=%4x",p)后并非为0。所以建议在free(p)后,立即加一句p=NULL。
3)检查p的地址 if(p!=NULL){ ... }
6.2 calloc/realloc
1)calloc()函数
void *calloc(size_t nmemb, size_t size);
参数nmemb 表示要分配元素的个数,size表示每个元素的大小,分频的内存空间大小是 nmemb*size; 返回值是 void* 类型的指针,指向分配好的内存首地址。
用法一:分配1024*sizeof(int)字节大小的内存,并清空为0
int *p = (int *)calloc(1024,sizeof(int));
用法二:与 alloc等价的 malloc 用法
int *p = (int *)malloc(1024*sizeof(int));
memset(p,0,1024*sizeof(int));
差异:用法一calloc,会根据分配的的类型来初始化为0,如:分配int型,则初始化为(int)0; 若为指针类型,则初始化为空指针;若为浮点,则初始化为浮点型。
用法二memset,不能保证初试化为空指针值和浮点型。(与NULL常量和浮点型的定义有关)
2)realloc()函数
realloc()用来重新分配正在使用的一块内存大小。
定义:
void *realloc(void *ptr, size_t size);
用法示例:
int *p = (int *)malloc(1024); //
p = (int *)realloc(512); // 重新分配为 512字节大小内存,缩小数据丢失
p = (int *)realloc(2048); // 重新分配为2048字节大小内存
注意:经过realloc()调整后的内存空间起始地址有可能与原来的不同。
摘录书籍
《ARM嵌入式Linux系统开发详解》 弓雷 等编著
《高质量嵌入式Linux C编程》 梁庚 等编著
笔记:程序内存管理 .bss .data .rodata .text stack heap的更多相关文章
- XV6学习笔记(2) :内存管理
XV6学习笔记(2) :内存管理 在学习笔记1中,完成了对于pc启动和加载的过程.目前已经可以开始在c语言代码中运行了,而当前已经开启了分页模式,不过是两个4mb的大的内存页,而没有开启小的内存页.接 ...
- C++复习12.程序内存管理
程序内存管理 20131006 一个程序在运行期间的内存是如何的对编写程序至关重要,之前整理的C++内存管理的知识和Java程序内存管理的知识.今天我们系统的整理一下程序的内存. 1.一个程序的内存有 ...
- linux kernel学习笔记-5内存管理_转
void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...
- C程序内存管理
C程序的内存管理 熟悉Java语言的肯定知道,Java中内存管理是由虚拟机帮助我们完毕的,在C/C++中可不是这样,程序猿须要自己去分配和回收内存空间.本文记录了C程序可运行文件的存储结构.在内存中的 ...
- Magenta源代码笔记(3) —— 内存管理【转】
转自:http://blog.csdn.net/boymax2/article/details/52550197 版权声明:本文为博主原创文章,未经博主允许不得转载. Magenta内核支持虚拟地址的 ...
- Java复习2.程序内存管理
前言: 国庆节的第三天,大家都回家了,一个人在宿舍好无聊.不过这年头与其说是出去玩不如是说出去挤,所以在学校里还是清闲的好.找工作不用担心了,到时候看着你们慢慢忙:插个话题,大学都没有恋爱过,总之各种 ...
- bss、data、text、heap(堆)与stack(栈)
bss段: bss段(bss segment)通常是指用来存放程序中未初始化的全局变量和静态变量(static)的一块内存区域. bss是英文Block Started by Symbol的简称. b ...
- JVM读书笔记之内存管理
对于从事C.C++程序开发人员来说,在内存管理领域,他们既是拥有最高权力的“皇帝”又是从事最基础工作的“劳动人民”--既拥有每一个对象的“所有权”,又负责每一个对象生命开始到终结的维护责任. 对于Ja ...
- Linux System Programming 学习笔记(九) 内存管理
1. 进程地址空间 Linux中,进程并不是直接操作物理内存地址,而是每个进程关联一个虚拟地址空间 内存页是memory management unit (MMU) 可以管理的最小地址单元 机器的体系 ...
随机推荐
- 1-ser2008系统封装实验报告
系统封装实验 1. 封装系统的原因 直接克隆系统会导致克隆后的系统和原系统的SID号一致,在许多实验中会因为SID号相同而影响实验效果(如活动目录) 2. 实验 首先看一下se ...
- OSI七层模型详解 TCP/IP协议
总结 OSI中的层 功能 TCP/IP协议族 应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等 表示层 数据格式化,代码转 ...
- 四种比较简单的图像显著性区域特征提取方法原理及实现-----> AC/HC/LC/FT。
laviewpbt 2014.8.4 编辑 Email:laviewpbt@sina.com QQ:33184777 最近闲来蛋痛,看了一些显著性检测的文章,只是简单的看看,并没有深入的研究,以 ...
- ImportError: No module named 'requests'
补充说明: 当前环境是在windows环境下 python版本是:python 3.4. 刚开始学习python,一边看书一边论坛里阅读感兴趣的代码, http://www.oschina.net/c ...
- 用字体在网页中画Icon图标
第一步,下载.IcoMoon网站选择字体图标并下载,解压后将fonts文件夹放在工程目录下.fonts文件夹内有四种格式的字体文件: 注:由于浏览器对每种字体的支持程度不一致,要想在所有浏览器中都显示 ...
- 《中国文明史》系列—外柔 VS 内厉
读启良的<中国文明史>,里面有谈到外柔而内厉——中国政府自古以来奉行的准则.大致意思是说,我华夏民族对待周边民族,历来是很友好的,即所谓的“柔”,而对待自己人,向来是“刚”或曰“厉”的. ...
- [LeetCode] Paint House 粉刷房子
There are a row of n houses, each house can be painted with one of the three colors: red, blue or gr ...
- [LeetCode] Construct Binary Tree from Preorder and Inorder Traversal 由先序和中序遍历建立二叉树
Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that ...
- 如何用卷积神经网络CNN识别手写数字集?
前几天用CNN识别手写数字集,后来看到kaggle上有一个比赛是识别手写数字集的,已经进行了一年多了,目前有1179个有效提交,最高的是100%,我做了一下,用keras做的,一开始用最简单的MLP, ...
- ViewPager实现引导页
1. 要使用ViewPager,必须要创建 PagerAdapter. 这里创建一个 ViewPagerAdapter来继承PagerAdapter public class ViewPagerAda ...