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