现在的位置: 首页 > 综合 > 正文

内存管理之初体验

2012年01月09日 ⁄ 综合 ⁄ 共 2129字 ⁄ 字号 评论关闭
    说是近来其实也有个把月了
    通过C语言实现AC字符串匹配算法,先是固定分配字符串长度实现功能、再就实际工程中关键字个数未知等情况进行了动态内存分配,这只后内存的回收和泄漏变成了不可回避的问题。gcc -g test.c -o test ./ac.c
    罗老师指点是:使用top命令看一下内存的占用情况,这也就是上周五的事情了。
    周末回去学学琴看看电影按下不表,这周效率也不是很高,直到昨晚大家睡下了那安静的半个小时,思路才真正明晰起来,今天上午也就告一段落了。

    回溯看来整体的进程和思路是这样的,不知到有没有走弯路

1、内存耗用情况的实时监控:
    先循环运行程序,直接添加while(1)不停歇,很快就会爆出SEGGMENTATION FAULT,添加sleep(1)后,程序倒是可以缓慢又有条不紊的运转起来了;
    这时新开终端使用“ps -ef”命令,查看当前运行程序的ID情况,找到测试使用的进程ID;
    使用“top -d 2 -p IDnum”以每2秒一次刷新的方式查看该进程(我们运行的程序)的内存占用情况,类似于如下的结果,看不太懂但是就以往经验不深究了,瞄着自己的目标继续走下去。
    这里学到一点点知识:
对于多核的电脑查看TOP结果会有点眼花缭乱,开启后按“1”即可把各个CPU的使用情况分开来
显示中VIRT是指程序运行的虚拟内存总量, RES是指被内存使用还未被放出的物理内存情况
具体还是看这里吧。结果VIRT确实越来越大了,但具体多大才会出错没有等它

2、程序内存分配回收错误查看
    这里主要使用了Valgrind工具,使用说明有很多,参数也有不少,但具体我使用了这个命令“valgrind --tool=memcheck --leak-check=full ./test”,之后加上了-v参数查看了具体报出的错误的位置。
    主要暴露的错误有两类
    其一:“Conditional jump or move depends on uninitialised value(s)”
这部分主要的问题在于使用了没有初始化的参数,就我个人而言对于刚分配内存的参数没有使用memset进行内存的清零处理。
memset(pointer*,0,sizeof(pointer));
或者使用
bzero(pointer*,sizeof(pointer));
这个错误一般也就处理了。
    最后的调试中通过-V参数的添加查看仍存在使用了未初始化参数的问题,找了N久发现了问题在于自己程序设计前后思想的不统一,最开始设计某数组长度为30,这之后依据获取关键字的长度对参数进行了内存(分配和)初始化,但最后进行逐个判断处理时候使用了从0到30的循环,修改初始化长度memset(x,0,sizeof()*30)即可。
    其二:“Invalid read of size 4”
    这个问题的主要原因在于读取尚未分配的内存的内容,看网上很多给出的例子都是多读n个字节,到自己程序的问题则是“Address 0x41f1638 is 0 bytes after a block of size 480 alloc'd”在480分配后的0个字节,看到这个的时候有点气馁,前天和龚同学聊到有关内存泄漏的问题,他说我应该多分配一些内存而不是理论上需要多少就分配多少,看到这个0我就有点打鼓,是不是在加上几字节能好用,好在又搜到了和我一样的错误的例子,不再算计这0字节的问题了,跑到源代码中自己找原因。
    很开心的是通过这两天内存的耳濡目染,看自己程序时候看问题也看得比较清楚,valgrind把问题定位到自己定义的两个队列上了。原来是自己对队列中节点内存的释放存在问题,自己喜欢用指针传来传去也就传出问题了,通过重新分配内存一一将队列该节点内容复制过来,处理后释放新分配的内存如此循环处理完队列所有节点内容。而队列节点的释放则放在了最后对AC进行destroy的函数里面。如此这般VALGRIND显示我的程序就木有错误了~~
程序媛淡淡的忧伤哈~

总结一下:
    学习了实时查看进程使用的内存情况以及使用valgrind工具检查程序问题,主要是内存问题的方法;
    对于自己的编程方式方法上,以后在分配内存和回收内存时候尤其是分配内存时,注意多考虑回收的方法,以简便处理为佳不要太卡丁卡卯的分配内存,这对处理内存数据和回收内存都造成了一定的麻烦;写多个子函数进行程序的封装过程中方便起见虽然返回什么的都是指针,但是为了防止对子函数中调用的全局变量指针以及内容造成不必要得影响,返回的指针最好在子函数中进行内存的分配和内存数据的赋值拷贝。还有一点就是内存分配后不要忘了memset()一下对分配的内存清个零。

    程序调试过程中各种百度谷歌后发现了不少好文章,舍不得看完就关掉碰巧找到了EVERNOTE便记录了下来,这里附上链接供以后问题的查阅和进一步学习:
http://www.ibm.com/developerworks/cn/linux/l-pow-debug/
http://www.51testing.com/?uid-170805-action-spacelist-type-blog-itemtypeid-5378
http://www.ibm.com/developerworks/cn/linux/l-cn-valgrind/

抱歉!评论已关闭.