Home » 未分类 » Linux C 学习笔记 十一

Linux C 学习笔记 十一

动态内存分配

stack

局部变量

函数执行(压栈、弹栈)

code 代码区(只能读,不能修改)

函数代码

字符串常量,所有双引号包裹的字符串

data 数据区

全局变量

静态变量(static修饰)

heap 堆区

 

动态内存分配

在程序中按照需要和在需要时分配内存的方式叫做动态分配内存,动态内存在堆上分配。

 

size_t 等同于当前平台的unsigned int

ssize_t ——————–> signed int

 

申请与释放

申请

malloc()

calloc()

realloc()

释放

free()

 

void *malloc(size_t size);

允许从空闲内存池中分配连续内存

size 参数是一个所需字节数的整数;

返回一个只想void类型的指针,在使用时要根据需要做强制类型转换

 

void *calloc(size_t num_elements,size_t element_size);

分配的内存被初始化为0

num_element:所需元素的数量

element_size:每个元素的字节数

 

void *realloc(void *ptr,size_t new_size);

必须是已经申请到了的内存,new_size 是表示新的内存的大小,而不是说你想要增加或者减少的值的多少。

ptr指向的内存基础上扩大或者缩小内存。

 

 

Void free(void *pointer)

 

 

 

api中说malloc是不会初始化的,但是实际上在程序运行时程序一开始时会初始化一下

 

malloc calloc的区别在于,calloc 申请后会初始化一下为0

 

 

 

//初始化

memset(p,0,sizeof(int));//清空工作,p指向刚刚申请的空间,0表示设置的值

//设置多长呢?就是sizeof(int)

 

 

在内存分配上realloc 如果还有足够的空间扩张,则其继续扩张,不够则在新的地址空间开辟一块,然后复制过去,然后释放原来旧的空间。扩张的时候不会释放。

 

 

free(void *pointer);

释放的指针必须是通过申请得到的,然后释放。

如果你不释放,到程序结束时,操作系统内核也会检测,但是建议程序员自己释放。

malloc calloc 一次必须释放一次。

 

 

 

常见错误

段错误:编译器不能自动发现发生内存错误,通常是在程序运行时才能捕捉到。没有明显的错误,时隐时现。

 

第一种错误:

内存分配不成功,却使用了它:编程新手常犯这种错误,因为没有意识到内存分配会不成功,常用解决办法,在使用内存之前检查指针是否为NULL

如果是用malloccallocrealloc来申请内存,应该用ifp == NULL)或ifp != NULL)进行防错处理。

即使有时候我们有剩余足够的空间,但由于有时候我们申请的空间过大,可能没有连续的足够大到我们申请的空间时,这时候也会申请失败。

 

也可以使用断言判断申请内存是否成功

#include<assert.h>//断言

//使用断言进行判断

//断言满足条件则程序继续执行,否之中断推出

p = NULL;

assert(p != NULL);

 

printf(“p:%p\n”,p);

 

第二种错误:

内存分配成功,但是尚未初始化就引用了它:一是没有初始化观念,二是误以为内存的缺省初始值玩全为零,导致引用初值错误。

所以无论用何种当时创建数组,都别忘了赋初值,即便是赋零值也不可以省略,不要嫌麻烦。

 

 

第三中错误:内存分配成功并且已经初始化,但操作越过了内存的边界。

如循环和递归的次数越界。

 

第四中错误:忘记了释放内存,造成内存泄漏。

含有这种错误的函数每次被调用一次就丢失一块内存,刚开始时系统的内存充足,你看不到错误,终有一次程序突然死掉,系统出现提示:内存耗尽。

动态内存的申请与释放必须配对,程序中mallocfree的使用次数一定要相同,否则肯定有错误(newdelete同理)。

Int *p = (int *)malloc(sizeof(int));

p = (int *)malloc(10*sizeof(int));

free(p);

这样第一次申请的第一块内存就找不见了。释放只是释放第二次申请到的。应该操作完之后就记得free一次;当然释放两次也是不行的,这时可能会告诉你double free() 程序崩溃。

建议在一个文件内申请的就在文件内释放,在模块申请的不要传递出去。

 

第五种错误:释放了内存却继续使用它

释放内存后变量内容不改变,依然会保留上一次使用的地址。释放后继续使用此内存属于非法访问

最好将已经释放的指针变量指空。

定义了指针没有赋值就变成了野指针,或者是释放了内存后继续使用指针也为野指针。

指针变量没有初始化。指针pfree或者delete之后,没有置为NULL,让人误以为p是个合法的指针,这两种都是野指针。

指针消亡了,并不表示它所指的内存会被自动释放。比如把指针指向其它的地方

内存被释放了,并不表示指针会消亡或者成了NULL指针

 

数据结构

以某种规则来定义数据存储的方式,使得数据单元和数据单元之间产生联系性。

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
void print_memory(int *start,int len)
{
int *p = start;
for(;p<start+len;p++)
{
printf(“%p—–>%d\n”,p,*p);
}

}

int main(void)
{

int *p =(int *)malloc(10*sizeof(int));
//初始化
memset(p,0,sizeof(int));//清空工作,p指向刚刚申请的空间,0表示设置的值
//设置多长呢?就是sizeof(int)

printf(“p:%p\n”,p);
print_memory(p,10);

printf(“\n”);

/*
int counter =0;

int *p = NULL;
int *q = (int *)malloc(sizeof(int));
*q = 100;

//while(!*((int *)malloc(4)))
while(p = (int *)malloc(sizeof(int)))
{
if(!p)
break;
if(*p == 0)
{ counter++;
// printf(“.”);
// fflush(stdout);
// printf(“\n%p\n”,p);
}
else
{
printf(“*”);
fflush(stdout);
}
}
free(q);
printf(“%d\n”,counter);
*/

int *pc = (int *)calloc(10,sizeof(int));
*pc =100;
print_memory(pc,10);
printf(“===================\n”);
pc = (int *)realloc(pc,20*sizeof(int));
print_memory(pc,20);

return 0;
}

This entry was posted in 未分类. Bookmark the permalink.