zhangcsdntest 2016-10-06
MMU=Segmentation Unit+Paging Unit //MMU: Memory Management Unit
logical address=>Segmentation Unit=>linear address=>Paging Unit=>physical address
#include <stdlib.h> void *malloc(size_t size);
#include<stdlib.h> int *p1=(int*)malloc(sizeof(int)); //会一口气分配33页, 把p1的管理信息放在p1之后的12byte int *p2=(int*)malloc(sizeof(int)); //因为p1时分配的33页还没用完, 所以直接分配在p1的管理信息后 //管理信息的区域可以写入,但是你写了之后free(p1)就会段错误,所以不要写 //超出33page的内存你访问都不行, 直接段错误
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<stdlib.h> int main(){ printf("当前进程进程号:%d\n",getpid()); int *pi=(int*)malloc(sizeof(int)); printf("pi=%p\n",pi); //0x21000 就是33个内存页//0x 1000 就是 1个内存页 //故意越界一下试试, 不超过33内存页的范围 *(pi+1024*30)=250; printf("*(pi+1024*30)=%d\n",*(pi+1024*30)); //没有发生段错误 //故意越界一下试试, 超过33内存页的范围 *(pi+1024*33)=250; //ATTENTION:pi是int*, 所以pi+1024*33可是pi+4*1024*33byte啊 printf("*(pi+1024*33)=%d\n",*(pi+1024*33)); //发生段错误 while(1); return 0; } /* $ ./a.out 当前进程进程号:2787 pi=0x9c40008 *(pi+1024*30)=250 Segmentation fault (core dumped) */
a) #include <stdlib.h> void free(void *ptr);
frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc()
Note:
void safefree(void **pp){ if(pp!=NULL&&*pp!=NULL){ free(*pp); *pp=NULL; } } #define safeFree(p) safeFree((void**)&(p)) int main(){ int *pi; pi=(int*)malloc(sizeof(int)); *pi=5; printf(“Before:%p\n”,pi); safefree(pi); printf(“After:%p\n”,pi); safefree(pi); return 0; }
#include <unistd.h> int getpagesize(void);
returns the number of bytes in a memory page, where "page" is a fixed-length block, the unit for memory allocation and file mapping performed by mmap(2).
#include <unistd.h> void *sbrk(intptr_t increment); //intptr_t 是int的别名, _t都可以认为是int的别名,偶尔是short 或long etc
调整动态内存/虚拟内存的大小, increments the program's data space by increment bytes. Calling sbrk() with an increment of 0 can be used to find the current location of the program break.(当前动态分配内存的末尾位置)(程序断点,program break,可以理解为offset的位置),成功返回the previous program break,失败返回(void*)-1
increment>0表示申请动态内存, 就是内存空间变大
increment=0表示获取当前动态内存的末尾地址, 就是内存空间不变
increment<0表示释放动态内存, 就是内存空间变小
#include<stdlib.h> #include<unistd.h> //使用sbrk()获取一个有效地址 void* pv=sbrk(0); if((void*)-1==pv) perror("sbrk"),exit(-1); //使用sbrk()在当前位置基础上申请一个int长度的内存 void* p2=sbrk(sizeof(int)); if((void*)-1==p2) perror("sbrk"),exit(-1);
Note:虽然sbrk()既能申请动态内存, 也能释放动态内存, 但是使用sbrk函数申请动态内存时更加方便,��般来说, 使用sbrk函数申请比较小块的动态内存时, 操作系统会映射1个内存页大小的内存空间, 当申请的动态内存超过1个内存也时, 系统会再次映射1个内存页的大小, 当所有动态内存释放完毕时, 系统不会保留任何的动态内存映射, 与malloc()相比, 比较节省内存空间, 也不会申请额外的存储空间, 但是频繁分配时效率没有malloc()高
#include <unistd.h> int brk(void *addr);
调整动态内存/虚拟内存的大小, sets the end of the data segment to the value specified by addr,成功返回0,失败返回-1, 设errno为ENOMEM
//使用brk()释放动态内存 #include<stdlib.h> #include<unistd.h> int res=brk(pv); if(-1==res) perror("brk"),exit(-1);
Note:虽然brk()既能申请动态内存, 又能释放动态内存, 但是释放动态内存更加方便, 而sbrk()申请动态内存更加方便, 因此一般情况下两个函数搭配使用, sbrk()专门用于申请, brk()专门用于释放
A memory leak occurs when allocated memory is never used again but is not freed !!!A problem with memory leaks is that the memory cannot be reclaimed and used later. The amount of memory available to the heap manager is decreased. If memory is repeatedly allocated and then lost, then the program may terminate when more memory is needed but malloc() cannot allocate it because it ran out of memory. In extreme cases, the operationg system may crash
losing the address:
int *pi=(int*)malloc(sizeof(int)); *pi=5; //之前申请的内存已经无法释放了,因为address已经丢了 … pi=(int*)malloc(sizeof(int);
Structure deallocation without free pointers defined in it. When memory is allocated for a strcture, the rentime system will not aytomaticallu allocate memory for any pointers defined within it. Likewise, when the structure goes away, the runtime system will not automatically deallocate memory asigned to the structure’s pointers
The correct way to allocate and deallocate a structure pointer with pointer fields:
void initializePerson(Person *person, sonst char* fn,const char * ln, const chat* title,uint age){ person->firstName=(char*)malloc(strlen(fn)+1); strcpy(person->firstName,fn); ... person->age=age; } void deallocatePerson(Person* person){ free(person->firstName); free(person->lastName); free(person->title); } void processPerson(){ Person* pPerson; pPerson=(Person*)malloc(sizeof(Person)); initilizePerson(pPterson,"Peter","Underwood","Manager",36); ... deallocatePerson(pPerson); free(pPerson); }
a pointer still references the original memory after it has been freed. The use of dangling pointer can result in:
Several approaches for pointer-induced problem:
Note:When a pointer is passed to a function, it is always good practice to verify it is not NULL before using it;
Several potential problems can occur when returning a pointer from a function:
This should be done carefully since the runtime system doesn’t verify that parameters used by a function pointer are correct.It is also possible to cast a function pointer to a different function pointer and then back. The resulting pointer will be equal to the original pointer, The size of function pointers used are not necessarily the same.
Note that conversion between function pointers and pointers to data is not guaranted to work;
Always make sure you use the correct argument list for function pointers, Failure to do so will result in indeterminate behavior