一、内存泄露
1、正常的链表操作
下面程序建立一个10元素的链表,输出它们的节点,每个节点是一个员工的工号和年龄。最后删除每个节点,释放列表。
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:%dn",mytempnd->number,mytempnd->age); } //然后删除链表中的所有元素 mynode* oldtmpnd; for (mytempnd=mylist->next;mytempnd!=NULL;){ printf("delete id:%dn",mytempnd->number); oldtmpnd=mytempnd; mytempnd=mytempnd->next; free(oldtmpnd); } free(mylist); return 0; }
下面是程序运行效果
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 %
下面演示了垃圾的形成,这是内存泄露的一种方式,即在链表中,某些节点与链表中的其它节点失去联系,导致无法删除,下面故意让第4个结点的next指针指向null,失去与后面6个元素的联系。
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:%dn",mytempnd->number,mytempnd->age); } //然后删除链表中的所有元素 for (mytempnd=mylist->next;mytempnd!=NULL;mytempnd=mytempnd->next){ printf("delete id:%dn",mytempnd->number); free(mytempnd); } free(mylist); //下面是形成内存泄露第一种情况-垃圾的演示 //生成并输出链表,这个与前面相同 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:%dn",mytempnd->number,mytempnd->age); } //删除链表,我们故意留下后面6个链表节点无法删除,导致后面6个链表节点形成垃圾 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:%dn",mytempnd->number); free(mytempnd); j++; } return 0; }
下面是程序运行效果
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:%dn",mytempnd->number,mytempnd->age); } //然后删除链表中的所有元素 mynode* oldtmpnd; for (mytempnd=mylist->next;mytempnd!=NULL;){ printf("delete id:%dn",mytempnd->number); oldtmpnd=mytempnd; mytempnd=mytempnd->next; free(oldtmpnd); } free(mylist); //下面是形成内存泄露第二种情况-悬挂指针的演示 //生成并输出链表,这个与前面相同 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:%dn",mytempnd->number,mytempnd->age); } //我们故意删除链表后面的4个节点,但是让第6个元素的next指向的地址无效, //仍指向已经删除的第7个节点,导致悬挂指针 printf ("-------------------------n"); int j=0; for (mytempnd=mylist->next;mytempnd!=NULL;){ oldtmpnd=mytempnd; mytempnd=mytempnd->next; if (++j>6){ printf("delete id:%dn",oldtmpnd->number); free(oldtmpnd); } } return 0; }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/482786.html