
1 引言
2 C/C++中内存分配

-
栈区(stack):由编译器自动分配与释放,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。其操做相似于数据结构中的栈。 -
堆区(heap):通常由程序员自动分配,若是程序员没有释放,程序结束时可能有OS回收。其分配相似于链表。 -
全局区(静态区static):数据段,程序结束后由系统释放。全局区分为已初始化全局区(data),用来存放保存全局的和静态的已初始化变量和未初始化全局区(bss),用来保存全局的和静态的未初始化变量。 -
常量区(文字常量区):数据段,存放常量字符串,程序结束后有系统释放。 -
代码区:存放函数体(类成员函数和全局区)的二进制代码,这个段在内存中通常被标记为只读,任何对该区的写操做都会致使段错误(Segmentation Fault)。
分配和管理方式不一样
malloc()
等这类实时内存分配函数来实现。当进程调用
malloc
等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用
free
等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
alloca()
函数进行分配,可是栈的动态分配和堆是不一样的,它的动态分配是由编译器进行释放,无需手工控制。
申请的大小限制不一样
申请效率不一样
-
栈由系统自动分配,速度快,可是程序员没法控制。 -
堆是有程序员本身分配,速度较慢,容易产生碎片,不过用起来方便。
产生碎片不一样
内存地址增加的方向不一样
-
堆是向着内存地址增长的方向增加的,从内存的低地址向高地址方向增加; -
栈的增加方向与之相反,是向着内存地址减少的方向增加,由内存的高地址向低地址方向增加。
main
调用函数
func1
,函数
func1
调用函数
func2
。当这个程序被操做系统调入内存运行时,其对应的进程在内存中的映射结果以下图所示

“缓冲区溢出”
。发生缓冲区溢出时,就会覆盖下一个相邻的内存块,致使程序发生一些不可预料的结果:也许程序能够继续,也许程序的执行出现奇怪现象,也许程序彻底失败或者崩溃等。
缓冲区溢出
没有保证足够的存储空间存储复制过来的数据
void function(char *str)
{
char buffer[10];
strcpy(buffer,str);
}
strcpy()
将直接把
str
中的内容
copy
到
buffer
中。这样只要
str
的长度大于 10 ,就会形成
buffer
的溢出,使程序运行出错。存在象
strcpy
这样的问题的标准函数还有
strcat(),sprintf(),vsprintf(),gets(),scanf()
等。对应的有更加安全的函数,即在函数名后加上
_s
,如
scanf_s()
函数。
-
严格检查输入长度和缓冲区长度。 -
常见的高危函数
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
整数溢出
-
宽度溢出:把一个宽度较大的操做数赋给宽度较小的操做数,就有可能发生数据截断或符号位丢失
#include<stdio.h>
int main()
{
signed int value1 = 10;
usigned int value2 = (unsigned int)value1;
}
-
算术溢出,该程序即便在接受用户输入的时候对a、b的赋值作安全性检查,a+b 依旧可能溢出:
#include<stdio.h>
int main()
{
int a;
int b;
int c=a*b;
return 0;
}
数组索引不在合法范围内
enum {TABLESIZE = 100};
int *table = NULL;
int insert_in_table(int pos, int value) {
if(!table) {
table = (int *)malloc(sizeof(int) *TABLESIZE);
}
if(pos >= TABLESIZE) {
return -1;
}
table[pos] = value;
return 0;
}
pos
为
int
类型,可能为负数,这会致使在数组所引用的内存边界以外进行写入,能够将
pos
类型改成
size_
t避免
空字符错误
//错误
char array[]={'0','1','2','3','4','5','6','7','8'};
//正确的写法应为:
char array[]={'0','1','2','3','4','5','6','7','8',’\0’};
//或者
char array[11]={'0','1','2','3','4','5','6','7','8','9’};

本文分享自微信公众号 - C语言入门到精通(c_printf)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。程序员