最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C指針原理教程之垃圾回收-內(nèi)存泄露

 更新時間:2019年02月07日 11:55:27   作者:myhaspl  
C語言沒有運(yùn)行時庫,無法自動壓縮使用中的內(nèi)存,縮小堆棧所需內(nèi)存空間。若只申請內(nèi)存,沒有釋放,勢必造成系統(tǒng)內(nèi)存不斷減少、丟失。長時間的運(yùn)行,最終導(dǎo)致系統(tǒng)死機(jī)。文章闡述了C語言垃圾產(chǎn)生的原因,并從引用計(jì)數(shù)、標(biāo)記一清除算法兩方面提出如何實(shí)現(xiàn)C語言的垃圾回收。

一、內(nèi)存泄露

1、正常的鏈表操作

下面程序建立一個10元素的鏈表,輸出它們的節(jié)點(diǎn),每個節(jié)點(diǎn)是一個員工的工號和年齡。最后刪除每個節(jié)點(diǎn),釋放列表。

dp@dp:~/memorytest % cat 1.c

#include <stdlib.h>
#include <stdio.h>
//code:myhaspl@myhaspl.com
//author:myhaspl
//date:2014-01-10
typedef struct listnode mynode; 
struct listnode{
  mynode *next;
  int number;
  int age;
  };
mynode *addnode(mynode *prevnd,int number,int age){
  mynode *ndtemp=(mynode*)malloc(sizeof(mynode));
  prevnd->next=ndtemp;
  ndtemp->number=number;
  ndtemp->age=age;
  ndtemp->next=NULL;
  return ndtemp;
}
mynode *initlist(){
  mynode *temp=(mynode*)malloc(sizeof(mynode));  
  temp->number=0;
  temp->age=0;
  temp->next=NULL;
  return temp;
}
int main(){
  mynode *mylist=initlist();
  mynode *mytempnd=mylist;
  int i=0;f懸掛指針
  for(i=0;i<10;i++){
    mytempnd=addnode(mytempnd,i,20+i);
  }
  //下面是正常的鏈表操作
  //先輸出鏈表元素
  for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){
    printf("id:%d,age:%d\n",mytempnd->number,mytempnd->age);
  }
  //然后刪除鏈表中的所有元素
  mynode* oldtmpnd;
  for (mytempnd=mylist->next;mytempnd!=NULL;){
    printf("delete id:%d\n",mytempnd->number);
    oldtmpnd=mytempnd;
    mytempnd=mytempnd->next;
    free(oldtmpnd);
  }
  free(mylist);
    return 0;  
}

下面是程序運(yùn)行效果

dp@dp:~/memorytest % gcc 1.c -o mytest

dp@dp:~/memorytest % ./mytest

id:0,age:20

id:1,age:21

id:2,age:22

id:3,age:23

id:4,age:24

id:5,age:25

id:6,age:26

id:7,age:27

id:8,age:28

id:9,age:29

delete id:0

delete id:1

delete id:2

delete id:3

delete id:4

delete id:5

delete id:6

delete id:7

delete id:8

delete id:9

dp@dp:~/memorytest % 

下面演示了垃圾的形成,這是內(nèi)存泄露的一種方式,即在鏈表中,某些節(jié)點(diǎn)與鏈表中的其它節(jié)點(diǎn)失去聯(lián)系,導(dǎo)致無法刪除,下面故意讓第4個結(jié)點(diǎn)的next指針指向null,失去與后面6個元素的聯(lián)系。

dp@dp:~/memorytest % cat 1.c


#include <stdlib.h>

#include <stdio.h>

//code:myhaspl@myhaspl.com

//author:myhaspl

//date:2014-01-10

typedef struct listnode mynode; 

struct listnode{

mynode *next;

int number;

int age;

};

mynode *addnode(mynode *prevnd,int number,int age){

mynode *ndtemp=(mynode*)malloc(sizeof(mynode));

prevnd->next=ndtemp;

ndtemp->number=number;

ndtemp->age=age;

ndtemp->next=NULL;

return ndtemp;

}

mynode *initlist(){

mynode *temp=(mynode*)malloc(sizeof(mynode));

temp->number=0;

temp->age=0;

temp->next=NULL;

return temp;

}

int main(){

mynode *mylist=initlist();

mynode *mytempnd=mylist;

int i=0;

for(i=0;i<10;i++){

mytempnd=addnode(mytempnd,i,20+i);

}

//下面是正常的鏈表操作

//先輸出鏈表元素

for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){

printf("id:%d,age:%d\n",mytempnd->number,mytempnd->age);

}

//然后刪除鏈表中的所有元素

for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){

printf("delete id:%d\n",mytempnd->number);

free(mytempnd);

}

free(mylist);

//下面是形成內(nèi)存泄露第一種情況-垃圾的演示

//生成并輸出鏈表,這個與前面相同

mylist=initlist();

mytempnd=mylist;

i=0;

for(i=0;i<10;i++){

mytempnd=addnode(mytempnd,i,20+i);

}

for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){

printf("id:%d,age:%d\n",mytempnd->number,mytempnd->age);

}

//刪除鏈表,我們故意留下后面6個鏈表節(jié)點(diǎn)無法刪除,導(dǎo)致后面6個鏈表節(jié)點(diǎn)形成垃圾

int j=0;

for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){

if (++j>3){

mytempnd->next=NULL;

break;

}

}

for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){

printf("delete id:%d\n",mytempnd->number);

free(mytempnd);

j++; 

}

    return 0;

}

下面是程序運(yùn)行效果

dp@dp:~/memorytest % gcc 1.c -o mytest

dp@dp:~/memorytest % ./mytest

id:0,age:20

id:1,age:21

id:2,age:22

id:3,age:23

id:4,age:24

id:5,age:25

id:6,age:26

id:7,age:27

id:8,age:28

id:9,age:29

delete id:0

delete id:1

delete id:2

delete id:3

delete id:4

delete id:5

delete id:6

delete id:7

delete id:8

delete id:9

id:0,age:20

id:1,age:21

id:2,age:22

id:3,age:23

id:4,age:24

id:5,age:25

id:6,age:26

id:7,age:27

id:8,age:28

id:9,age:29

delete id:0

delete id:1

delete id:2

delete id:3

dp@dp:~/memorytest %

3、懸掛指針

一個指針不為空,但是指向一個無效的地址或耒知對象的地址,則這樣的指針稱為懸掛指針。

dp@dp:~/memorytest % cat 2.c

#include <stdio.h>

#include <stdlib.h>

//code:myhaspl@myhaspl.com

//author:myhaspl

//date:2014-01-10

typedef struct listnode mynode;

struct listnode{

mynode *next;

int number;

int age;

};

mynode *addnode(mynode *prevnd,int number,int age){

mynode *ndtemp=(mynode*)malloc(sizeof(mynode));

prevnd->next=ndtemp;

ndtemp->number=number;

ndtemp->age=age;

ndtemp->next=NULL;

return ndtemp;

}

mynode *initlist(){

mynode *temp=(mynode*)malloc(sizeof(mynode));

temp->number=0;

temp->age=0;

temp->next=NULL;

return temp;

}

int main(){

mynode *mylist=initlist();

mynode *mytempnd=mylist;

int i=0;

for(i=0;i<10;i++){

mytempnd=addnode(mytempnd,i,20+i);

}

//下面是正常的鏈表操作

//先輸出鏈表元素

for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){

printf("id:%d,age:%d\n",mytempnd->number,mytempnd->age);

}

//然后刪除鏈表中的所有元素

mynode* oldtmpnd;

for (mytempnd=mylist->next;mytempnd!=NULL;){

printf("delete id:%d\n",mytempnd->number);

oldtmpnd=mytempnd;

mytempnd=mytempnd->next;

free(oldtmpnd);

}

free(mylist);

//下面是形成內(nèi)存泄露第二種情況-懸掛指針的演示

//生成并輸出鏈表,這個與前面相同

mylist=initlist();

mytempnd=mylist;

i=0;

for(i=0;i<10;i++){

mytempnd=addnode(mytempnd,i,20+i);

}

for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){

printf("id:%d,age:%d\n",mytempnd->number,mytempnd->age);

}

//我們故意刪除鏈表后面的4個節(jié)點(diǎn),但是讓第6個元素的next指向的地址無效,

//仍指向已經(jīng)刪除的第7個節(jié)點(diǎn),導(dǎo)致懸掛指針

printf ("-------------------------\n");

int j=0;

for (mytempnd=mylist->next;mytempnd!=NULL;){

oldtmpnd=mytempnd;

mytempnd=mytempnd->next;

if (++j>6){

printf("delete id:%d\n",oldtmpnd->number);

free(oldtmpnd);

}

}

    return 0;

}

執(zhí)行程序

dp@dp:~/memorytest % gcc 2.c -o mytest

dp@dp:~/memorytest % ./mytest

id:0,age:20

id:1,age:21

id:2,age:22

id:3,age:23

id:4,age:24

id:5,age:25

id:6,age:26

id:7,age:27

id:8,age:28

id:9,age:29

delete id:0

delete id:1

delete id:2

delete id:3

delete id:4

delete id:5

delete id:6

delete id:7

delete id:8

delete id:9

id:0,age:20

id:1,age:21

id:2,age:22

id:3,age:23

id:4,age:24

id:5,age:25

id:6,age:26

id:7,age:27

id:8,age:28

id:9,age:29

delete id:6

delete id:7

delete id:8

delete id:9

但是注意free函數(shù)表示釋放,這個釋放指的是把這段內(nèi)存標(biāo)記成可用狀態(tài),或者說,沒有人在用這段內(nèi)存了,也就是意味著如果這段內(nèi)存如果沒有被操作系統(tǒng)重新使用,里面的數(shù)據(jù)還存在,如果被操作系統(tǒng)分配給其它程序或本程序的其它內(nèi)存塊申請之用,則數(shù)據(jù)會被清空。

3、下面是形成內(nèi)存泄露第三種情況-共享的演示,多個指針指向同一個內(nèi)存,這個內(nèi)存因?yàn)槟硞€指針不再使用的原因刪除,導(dǎo)致其它指針指向一個無效地址

dp@dp:~/memorytest % cat 2.c


#include <stdio.h>

#include <stdlib.h>

//code:myhaspl@myhaspl.com

//author:myhaspl

//date:2014-01-10

typedef struct listnode mynode;

struct listnode{

mynode *next;

char *data;

int number;

int age;

};

mynode *addnode(mynode *prevnd,int number,int age,char *data){

mynode *ndtemp=(mynode*)malloc(sizeof(mynode));

prevnd->next=ndtemp;

ndtemp->number=number;

ndtemp->age=age;

ndtemp->data=data;

ndtemp->next=NULL;

return ndtemp;

}

mynode *initlist(){

mynode *temp=(mynode*)malloc(sizeof(mynode));

temp->number=0;

temp->age=0;

temp->data=NULL;

temp->next=NULL;

return temp;

}

int main(){

    //下面是形成內(nèi)存泄露第三種情況-共享的演示,多個指針指向同一個內(nèi)存,這個內(nèi)存因?yàn)槟硞€指針不再使用的原因刪除,

//生成并輸出鏈表,生成1個鏈表(共3個元素),元素的data都指向同一個內(nèi)存塊

mynode *mylist=initlist();

mynode *mytempnd=mylist;

char *mydata=(char *)malloc(100);

const char *strsrc="helloworld";

strcpy(mydata,strsrc);

int i=0;

for(i=0;i<3;i++){

    mytempnd=addnode(mytempnd,i,20+i,mydata);

}

for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){

printf("id:%d,age:%d,data:%s\n",mytempnd->number,mytempnd->age,mytempnd->data);

    }

//下面將導(dǎo)致共享的內(nèi)存釋放,但仍有2個結(jié)點(diǎn)指向這個內(nèi)存,這將導(dǎo)致內(nèi)存泄露

//我們故意刪除最后一個節(jié)點(diǎn),并釋放最后一個結(jié)點(diǎn)的data指針指向的內(nèi)存

printf ("-------------------------\n");

mynode *oldtmpnd;

for (mytempnd=mylist->next;mytempnd!=NULL;){

oldtmpnd=mytempnd;

mytempnd=mytempnd->next;

if (mytempnd==NULL){

printf("delete id:%d\n",oldtmpnd->number);

free(oldtmpnd->data);

free(oldtmpnd);

}

}

    return 0;

}

執(zhí)行程序:

dp@dp:~/memorytest % gcc 2.c -o mytest

2.c: In function 'main':

2.c:37: warning: incompatible implicit declaration of built-in function 'strcpy'

dp@dp:~/memorytest % ./mytest

id:0,age:20,data:helloworld

id:1,age:21,data:helloworld

id:2,age:22,data:helloworld

delete id:2

dp@dp:~/memorytest % 

相關(guān)文章

  • C語言遞歸思想實(shí)現(xiàn)漢諾塔詳解

    C語言遞歸思想實(shí)現(xiàn)漢諾塔詳解

    大家好,本篇文章主要講的是C語言遞歸思想實(shí)現(xiàn)漢諾塔詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • C語言版五子棋游戲的實(shí)現(xiàn)代碼

    C語言版五子棋游戲的實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了C語言版五子棋游戲的實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++淺析析構(gòu)函數(shù)的特征

    C++淺析析構(gòu)函數(shù)的特征

    既然在創(chuàng)建對象時有構(gòu)造函數(shù)(給成員初始化),那么在銷毀對象時應(yīng)該還有一個清除成員變量數(shù)據(jù)的操作咯,析構(gòu)函數(shù)與構(gòu)造函數(shù)功能相反,析構(gòu)函數(shù)不是完成對象的銷毀,局部對象銷毀工作是由編譯器完成的。而對象在銷毀時會自動調(diào)用析構(gòu)函數(shù),完成類的一些資源清理工作
    2022-07-07
  • C++初階之list的模擬實(shí)現(xiàn)過程詳解

    C++初階之list的模擬實(shí)現(xiàn)過程詳解

    在C++中我們經(jīng)常使用STL,那個在那些我們常用的數(shù)據(jù)結(jié)構(gòu)vector,list的背后,又是如何實(shí)現(xiàn)的呢?這篇文章主要給大家介紹了關(guān)于C++初階之list的模擬實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • C語言實(shí)現(xiàn)BMP圖像閉運(yùn)算處理

    C語言實(shí)現(xiàn)BMP圖像閉運(yùn)算處理

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)BMP圖像閉運(yùn)算處理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 華為云開發(fā)工具CodeArts IDE for C/C++開發(fā)使用指南

    華為云開發(fā)工具CodeArts IDE for C/C++開發(fā)使用指南

    CodeArts IDE是一個集成開發(fā)環(huán)境(IDE),它提供了開發(fā)語言和調(diào)試服務(wù),本文主要介紹了華為云開發(fā)工具CodeArts IDE for C/C++ 開發(fā)使用指南,感興趣的可以了解一下
    2023-08-08
  • 淺析C++ 仿函數(shù)

    淺析C++ 仿函數(shù)

    這篇文章主要介紹了C++ 仿函數(shù)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-08-08
  • c語言實(shí)現(xiàn)整蠱朋友小程序(附源碼)

    c語言實(shí)現(xiàn)整蠱朋友小程序(附源碼)

    這篇文章主要給大家介紹了關(guān)于c語言實(shí)現(xiàn)整蠱朋友小程序的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Opencv實(shí)現(xiàn)拼圖板游戲

    Opencv實(shí)現(xiàn)拼圖板游戲

    這篇文章主要為大家詳細(xì)介紹了Opencv實(shí)現(xiàn)拼圖板小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • Ubuntu16.04下配置VScode的C/C++開發(fā)環(huán)境

    Ubuntu16.04下配置VScode的C/C++開發(fā)環(huán)境

    這篇文章主要介紹了Ubuntu16.04下配置VScode的C/C++開發(fā)環(huán)境的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03

最新評論

志丹县| 东乡县| 普兰店市| 安岳县| 米泉市| 东乌| 钟山县| 呼和浩特市| 镇原县| 台东县| 黑水县| 柳河县| 会东县| 清流县| 磐石市| 博爱县| 施秉县| 静安区| 渑池县| 比如县| 泰宁县| 香港| 正蓝旗| 永兴县| 漳平市| 陆河县| 西乌珠穆沁旗| 特克斯县| 华亭县| 丰台区| 武功县| 浠水县| 天津市| 汤原县| 呼伦贝尔市| 莒南县| 观塘区| 霍林郭勒市| 卓资县| 垣曲县| 治县。|