铁血丹心

 找回密码
 我要成为铁血侠客
搜索
查看: 2444|回复: 2

[lua复刻] 游泳鱼0.66版本关于链表释放的疑问

[复制链接]
发表于 2011-12-31 12:17 | 显示全部楼层 |阅读模式

马上注册,结交更多侠友!

您需要 登录 才可以下载或查看,没有账号?我要成为铁血侠客

x
本帖最后由 蓝烟清 于 2011-12-31 16:31 编辑

这几天一直很郁闷,游戏老跳出,无任何提示。找了很久,原来是链表释放内存的问题,很不解,先给源码(在JY_PicInit函数)
清除表面内容
  1. //如果链表不为空,删除全部链表
  2.     list_for_each_safe(pos,p,&cache_head){
  3.         struct CacheNode *tmp= list_entry(pos, struct CacheNode , list);
  4.                 int picid = tmp->id;
  5.                 int fileid = tmp->fileid;
  6.         if(tmp->s!=NULL)
  7.                         SDL_FreeSurface(tmp->s);       //删除表面
  8.                 list_del(pos);
  9.                 SafeFree(tmp);

  10.         }
复制代码
清除pic内存
  1. for(i=0;i<PIC_FILE_NUM;i++){
  2.         pic_file[i].num =0;
  3.         SafeFree(pic_file[i].idx);
  4.         SafeFree(pic_file[i].grp);
  5.         SafeFree(pic_file[i].pcache);
  6.         if(pic_file[i].fp){
  7.             fclose(pic_file[i].fp);
  8.             pic_file[i].fp=NULL;
  9.         }

  10.     }
复制代码
很关键的一点:在清除PIC内存的时候,没有循环pcache进行free

或许有人认为在清除表面的时候已经SafeFree(tmp);,但是实际上并没有
可以把内容再打印出来
  1. //如果链表不为空,删除全部链表
  2.     list_for_each_safe(pos,p,&cache_head){
  3.         struct CacheNode *tmp= list_entry(pos, struct CacheNode , list);
  4.                 int picid = tmp->id;
  5.                 int fileid = tmp->fileid;
  6.         if(tmp->s!=NULL)
  7.                         SDL_FreeSurface(tmp->s);       //删除表面
  8.                 list_del(pos);
  9.                 SafeFree(tmp);

  10.                 if(pic_file[fileid].pcache && pic_file[fileid].pcache[picid]){
  11.                         JY_Debug("list  free cache %d fileid=%d  failed", picid, fileid);
  12.                 }
  13.         }
复制代码
在debug.txt就会看到这样类似的东西
11:46:45 list  free cache 36 fileid=0  failed
11:46:45 list  free cache 76 fileid=0  failed
11:46:45 list  free cache 1157 fileid=0  failed
11:46:45 list  free cache 1622 fileid=0  failed
11:46:45 list  free cache 1181 fileid=0  failed
11:46:45 list  free cache 1151 fileid=0  failed
11:46:45 list  free cache 1143 fileid=0  failed


说明实际上在清除链表的表面内容时,并没有把pache同时删除。

我是这样理解的
这样就会造成在切换场景(JY_PicInit函数在每切换一次场景时就调用)的时候,不断的造成内存泄漏,而且经过测试,cache下挂的Surface也没有被清除

不知道理解对不对


还有一点
if(tmp->s!=NULL)
                        SDL_FreeSurface(tmp->s);       //删除表面

应该也要改成
if(tmp->s!=NULL) {
                        SDL_FreeSurface(tmp->s);       //删除表面
                   tmp->s = NULL;  //避免野指针
}



List的作用是为了防止Surface过多,造成内存消耗过大。 但是遍历清空时这个为什么清不掉,原因为何,搞不明白啊
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2011-12-31 19:34 | 显示全部楼层
你如果不介意,现在可以打包发过来吗? 可以帮你查一查 qq 离线文件 78265172,借以就算了哈哈
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2012-1-1 02:16 | 显示全部楼层
SafeFree(tmp) 等于
if (tmp)
{
   free(tmp);
   tmp = NULL;
}
所以这里不会有错,不会产生野指针。你贴出这段代码我看不出有问题。
你好好检测你之前传的tmp是否是一个有效的表面,如果是无效表面,c里面这样释放的话就会有可能造成程序崩溃。

【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。

本版积分规则

小黑屋|手机版|铁血丹心

GMT+8, 2024-5-17 19:06

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表