当前位置:文档之家› 如何在linux下检测内存泄漏

如何在linux下检测内存泄漏

如何在linux下检测内存泄漏
如何在linux下检测内存泄漏

如何在linux下检测内存泄漏

简介:本文针对linux下的C++程序的内存泄漏的检测方法及其实现进行探讨。其中包括C++中的new和delete的基本原理,内存检测子系统的实现原理和具体方法,以及内存泄漏检测的高级话题。作为内存检测子系统实现的一部分,提供了一个具有更好的使用特性的互斥体(Mutex)类。

1.开发背景

在windows下使用VC编程时,我们通常需要DEBUG模式下运行程序,而后调试器将在退出程序时,打印出程序运行过程中在堆上分配而没有释放的内存信息,其中包括代码文件名、行号以及内存大小。该功能是MFC Framework提供的内置机制,封装在其类结构体系内部。

在linux或者unix下,我们的C++程序缺乏相应的手段来检测内存信息,而只能使用top指令观察进程的动态内存总额。而且程序退出时,我们无法获知任何内存泄漏信息。为了更好的辅助在linux下程序开发,我们在我们的类库项目中设计并实现了一个内存检测子系统。下文将简述C++中的new和delete的基本原理,并讲述了内存检测子系统的实现原理、实现中的技巧,并对内存泄漏检测的高级话题进行了讨论。

2.New和delete的原理

当我们在程序中写下new和delete时,我们实际上调用的是C++语言内置的new operator和delete operator。所谓语言内置就是说我们不能更改其含义,它的功能总是一致的。以new operator为例,它总是先分配足够的内存,而后再调用相应的类型的构造函数初始化该内存。而delete operator总是先调用该类型的析构函数,而后释放内存(图1)。我们能够施加影响力的事实上就是new operator和delete operator 执行过程中分配和释放内存的方法。

new operator为分配内存所调用的函数名字是operator new,其通常的形式是void * operator

new(size_t size);其返回值类型是void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。参数size确定分配多少内存,你能增加额外的参数重载函数operator new,但是第一个参数类型必须是size_t。

delete operator为释放内存所调用的函数名字是operator delete,其通常的形式是void operator delete(void *memoryToBeDeallocated);它释放传入的参数所指向的一片内存区。

这里有一个问题,就是当我们调用new operator分配内存时,有一个size参数表明需要分配多大的内存。但是当调用delete operator时,却没有类似的参数,那么delete operator如何能够知道需要释放该指针指向的内存块的大小呢?答案是:对于系统自有的数据类型,语言本身就能区分内存块的大小,而对于自定义数据类型(如我们自定义的类),则operator new和operator delete之间需要互相传递信息。

当我们使用operator new为一个自定义类型对象分配内存时,实际上我们得到的内存要比实际对象的内存大一些,这些内存除了要存储对象数据外,还需要记录这片内存的大小,此方法称为cookie。这一点上的实现依据不同的编译器不同。(例如MFC选择在所分配内存的头部存储对象实际数据,而后面的部分存储边界标志和内存大小信息。g++则采用在所分配内存的头4个自己存储相关信息,而后面的内存存储对象实际数据。)当我们使用delete operator进行内存释放操作时,delete operator就可以根据这些信息正确的释放指针所指向的内存块。

以上论述的是对于单个对象的内存分配/释放,当我们为数组分配/释放内存时,虽然我们仍然使用new operator和delete operator,但是其内部行为却有不同:new operator调用了operator new的数组版的兄弟-operator new[],而后针对每一个数组成员调用构造函数。而delete operator先对每一个数组成员调用析构函数,而后调用operator delete[]来释放内存。需要注意的是,当我们创建或释放由自定义数据类型所

构成的数组时,编译器为了能够标识出在operator delete[]中所需释放的内存块的大小,也使用了编译器相关的cookie技术。

综上所述,如果我们想检测内存泄漏,就必须对程序中的内存分配和释放情况进行记录和分析,也就是说我们需要重载operator new/operator new[];operator delete/operator delete[]四个全局函数,以截获我们所需检验的内存操作信息。

3.内存检测的基本实现原理

上文提到要想检测内存泄漏,就必须对程序中的内存分配和释放情况进行记录,所能够采取的办法就是重载所有形式的operator new和operator delete,截获new operator和delete operator执行过程中的内存操作信息。下面列出的就是重载形式

void* operator new( size_t nSize, char* pszFileName, int nLineNum )

void* operator new[]( size_t nSize, char* pszFileName, int nLineNum )

void operator delete( void *ptr )

void operator delete[]( void *ptr )

我们为operator new定义了一个新的版本,除了必须的size_t nSize参数外,还增加了文件名和行号,这里的文件名和行号就是这次new operator操作符被调用时所在的文件名和行号,这个信息将在发现内存泄漏时输出,以帮助用户定位泄漏具体位置。对于operator delete,因为无法为之定义新的版本,我们直接覆盖了全局的operator delete的两个版本。

在重载的operator new函数版本中,我们将调用全局的operator new的相应的版本并将相应的size_t 参数传入,而后,我们将全局operator new 返回的指针值以及该次分配所在的文件名和行号信息记录下来,这里所采用的数据结构是一个STL 的map,以指针值为key 值。当operator delete 被调用时,如果调用方式正确的话(调用方式不正确的情况将在后面详细描述),我们就能以传入的指针值在map 中找到相应的数据项并将之删除,而后调用free 将指针所指向的内存块释放。当程序退出的时候,map 中的剩余的数据项就是我们企图检测的内存泄漏信息--已经在堆上分配但是尚未释放的分配信息。

以上就是内存检测实现的基本原理,现在还有两个基本问题没有解决:

1) 如何取得内存分配代码所在的文件名和行号,并让new operator 将之传递给我们重载的operator new。

2) 我们何时创建用于存储内存数据的map 数据结构,如何管理,何时打印内存泄漏信息。

先解决问题1。首先我们可以利用 C 的预编译宏__FILE__ 和__LINE__,这两个宏将在编译时在指定位置展开为该文件的文件名和该行的行号。而后我们需要将缺省的全局new operator 替换为我们自定义的能够传入文件名和行号的版本,我们在子系统头文件MemRecord.h 中定义:

#define DEBUG_NEW new(__FILE__, __LINE__ )

而后在所有需要使用内存检测的客户程序的所有的cpp 文件的开头加入

#include "MemRecord.h"

#define new DEBUG_NEW

就可以将客户源文件中的对于全局缺省的new operator 的调用替换为new (__FILE__,__LINE__) 调用,而该形式的new operator将调用我们的operator new (size_t nSize, char* pszFileName, int nLineNum),其中nSize 是由new operator 计算并传入的,而new 调用点的文件名和行号是由我们自定义版本的new operator 传入的。我们建议在所有用户自己的源代码文件中都加入上述宏,如果有的文件中使用内存检测子系统而有的没有,则子系统将可能因无法监控整个系统而输出一些泄漏警告。

再说第二个问题。我们用于管理客户信息的这个map 必须在客户程序第一次调用new operator 或者delete operator 之前被创建,而且在最后一个new operator 和delete operator 调用之后进行泄漏信

息的打印,也就是说它需要先于客户程序而出生,而在客户程序退出之后进行分析。能够包容客户程序生命周期的确有一人--全局对象(appMemory)。我们可以设计一个类来封装这个map 以及这对它的插入删除操作,然后构造这个类的一个全局对象(appMemory),在全局对象(appMemory)的构造函数中创建并初始化这个数据结构,而在其析构函数中对数据结构中剩余数据进行分析和输出。Operator new 中将调用这个全局对象(appMemory)的insert 接口将指针、文件名、行号、内存块大小等信息以指针值为key 记录到map 中,在operator delete 中调用erase 接口将对应指针值的map 中的数据项删除,注意不要忘了对map 的访问需要进行互斥同步,因为同一时间可能会有多个线程进行堆上的内存操作。

好啦,内存检测的基本功能已经具备了。但是不要忘了,我们为了检测内存泄漏,在全局的operator new 增加了一层间接性,同时为了保证对数据结构的安全访问增加了互斥,这些都会降低程序运行的效率。因此我们需要让用户能够方便的enable 和disable 这个内存检测功能,毕竟内存泄漏的检测应该在程序的调试和测试阶段完成。我们可以使用条件编译的特性,在用户被检测文件中使用如下宏定义:

#include "MemRecord.h"

#if defined( MEM_DEBUG )

#define new DEBUG_NEW

#endif

当用户需要使用内存检测时,可以使用如下命令对被检测文件进行编译

g++ -c -DMEM_DEBUG xxxxxx.cpp

就可以enable 内存检测功能,而用户程序正式发布时,可以去掉-DMEM_DEBUG 编译开关来disable 内存检测功能,消除内存检测带来的效率影响。

图2所示为使用内存检测功能后,内存泄漏代码的执行以及检测结果

图2

4.错误方式删除带来的问题

以上我们已经构建了一个具备基本内存泄漏检测功能的子系统,下面让我们来看一下关于内存泄漏方面的一些稍微高级一点的话题。

首先,在我们编制c++ 应用时,有时需要在堆上创建单个对象,有时则需要创建对象的数组。关于new 和delete 原理的叙述我们可以知道,对于单个对象和对象数组来说,内存分配和删除的动作是大不相同的,我们应该总是正确的使用彼此搭配的new 和delete 形式。但是在某些情况下,我们很容易犯错误,比如如下代码:

class Test {};

……

Test* pAry = new Test[10];//创建了一个拥有 10 个 Test 对象的数组

Test* pObj = new Test;//创建了一个单对象

……

delete []pObj;//本应使用单对象形式 delete pObj 进行内存释放,却错误的使用了数

//组形式

delete pAry;//本应使用数组形式 delete []pAry 进行内存释放,却错误的使用了单对

//象的形式

不匹配的new 和delete 会导致什么问题呢?C++ 标准对此的解答是"未定义",就是说没有人向你保证会发生什么,但是有一点可以肯定:大多不是好事情--在某些编译器形成的代码中,程序可能会崩溃,而另外一些编译器形成的代码中,程序运行可能毫无问题,但是可能导致内存泄漏。

既然知道形式不匹配的new 和delete 会带来的问题,我们就需要对这种现象进行毫不留情的揭露,毕竟我们重载了所有形式的内存操作operator new,operator new[],operator delete,operator delete[]。

我们首先想到的是,当用户调用特定方式(单对象或者数组方式)的operator new 来分配内存时,我们可以在指向该内存的指针相关的数据结构中,增加一项用于描述其分配方式。当用户调用不同形式的operator delete 的时候,我们在map 中找到与该指针相对应的数据结构,然后比较分配方式和释放方式是否匹配,匹配则在map 中正常删除该数据结构,不匹配则将该数据结构转移到一个所谓"ErrorDelete" 的list 中,在程序最终退出的时候和内存泄漏信息一起打印。

上面这种方法是最顺理成章的,但是在实际应用中效果却不好。原因有两个,第一个原因我们上面已经提到了:当new 和delete 形式不匹配时,其结果"未定义"。如果我们运气实在太差--程序在执行不匹配的delete 时崩溃了,我们的全局对象(appMemory)中存储的数据也将不复存在,不会打印出任何信息。第二个原因与编译器相关,前面提到过,当编译器处理自定义数据类型或者自定义数据类型数组的new 和delete 操作符的时候,通常使用编译器相关的cookie 技术。这种cookie 技术在编译器中可能的实现方式是:new operator 先计算容纳所有对象所需的内存大小,而后再加上它为记录cookie 所需要的内存量,再将总容量传给operator new 进行内存分配。当operator new 返回所需的内存块后,new operator 将在调用相应次数的构造函数初始化有效数据的同时,记录cookie 信息。而后将指向有效数据的指针返回给用户。也就是说我们重载的operator new 所申请到并记录下来的指针与new operator 返回给调用者的指针不一定一致(图3)。当调用者将new operator 返回的指针传给delete operator 进行内存释放时,如果其调用形式相匹配,则相应形式的delete operator 会作出相反的处理,即调用相应次数的析构函数,再通过指向有效数据的指针位置找出包含cookie 的整块内存地址,并将其传给operator delete 释放内存。如果调用形式不匹配,delete operator 就不会做上述运算,而直接将指向有效数据的指针(而不是真正指向整块内存的指针)传入operator delete。因为我们在operator new 中记录的是我们所分配的整块内存的指针,而现在传入operator delete 的却不是,所以就无法在全局对象(appMemory)所记录的数据中找到相应的内存分配信息。

图3

综上所述,当new 和delete 的调用形式不匹配时,由于程序有可能崩溃或者内存子系统找不到相应的内存分配信息,在程序最终打印出"ErrorDelete" 的方式只能检测到某些"幸运"的不匹配现象。但我们总得做点儿什么,不能让这种危害极大的错误从我们眼前溜走,既然不能秋后算帐,我们就实时输出一个warning 信息来提醒用户。什么时候抛出一个warning 呢?很简单,当我们发现在operator delete 或operator delete[] 被调用的时候,我们无法在全局对象(appMemory)的map 中找到与传入的指针值相对应的内存分配信息,我们就认为应该提醒用户。

既然决定要输出warning信息,那么现在的问题就是:我们如何描述我们的warning信息才能更便于用户定位到不匹配删除错误呢?答案:在warning 信息中打印本次delete 调用的文件名和行号信息。这可有点困难了,因为对于operator delete 我们不能向对象operator new 一样做出一个带附加信息的重载版本,我们只能在保持其接口原貌的情况下,重新定义其实现,所以我们的operator delete 中能够得到的输入只有指针值。在new/delete 调用形式不匹配的情况下,我们很有可能无法在全局对象(appMemory)的map 中找到原来的new 调用的分配信息。怎么办呢?万不得已,只好使用全局变量了。我们在检测子系统的实现文件中定义了两个全局变量(DELETE_FILE,DELETE_LINE)记录operator delete 被调用时的文件名和行号,同时为了保证并发的delete 操作对这两个变量访问同步,还使用了一个mutex(至于为什么是CCommonMutex 而不是一个pthread_mutex_t,在"实现上的问题"一节会详细论述,在这里它的作用就是一个mutex)。

char DELETE_FILE[ FILENAME_LENGTH ] = {0};

int DELETE_LINE = 0;

CCommonMutex globalLock;

而后,在我们的检测子系统的头文件中定义了如下形式的DEBUG_DELETE

extern char DELETE_FILE[ FILENAME_LENGTH ];

extern int DELETE_LINE;

extern CCommonMutex globalLock;//在后面解释

#define DEBUG_DELETE globalLock.Lock(); \

if (DELETE_LINE != 0) BuildStack();\ (//见第六节解释)

strncpy( DELETE_FILE, __FILE__,FILENAME_LENGTH - 1 );\

DELETE_FILE[ FILENAME_LENGTH - 1 ]= '\0'; \

DELETE_LINE = __LINE__; \

delete

在用户被检测文件中原来的宏定义中添加一条:

#include "MemRecord.h"

#if defined( MEM_DEBUG )

#define new DEBUG_NEW

#define delete DEBUG_DELETE

#endif

这样,在用户被检测文件调用delete operator 之前,将先获得互斥锁,然后使用调用点文件名和行号对相应的全局变量(DELETE_FILE,DELETE_LINE)进行赋值,而后调用delete operator。当delete operator 最终调用我们定义的operator delete 的时候,在获得此次调用的文件名和行号信息后,对文件名和行号全局变量(DELETE_FILE,DELETE_LINE)重新初始化并打开互斥锁,让下一个挂在互斥锁上的delete operator 得以执行。

在对delete operator 作出如上修改以后,当我们发现无法经由delete operator 传入的指针找到对应的内存分配信息的时候,就打印包括该次调用的文件名和行号的warning。

天下没有十全十美的事情,既然我们提供了一种针对错误方式删除的提醒方法,我们就需要考虑以下几种异常情况:

1.用户使用的第三方库函数中有内存分配和释放操作。或者用户的被检测进程中进行内存分配和释放的实现文件没有使用我们的宏定义。由于我们替换了全局的operator delete,这种情况下的用户调用的delete 也会被我们截获。用户并没有使用我们定义的DEBUG_NEW 宏,所以我们无法在我们的全局对象(appMemory)数据结构中找到对应的内存分配信息,但是由于它也没有使用DEBUG_DELETE,我们为delete 定义的两个全局DELETE_FILE 和DELETE_LINE 都不会有值,因此可以不打印warning。

2.用户的一个实现文件调用了new 进行内存分配工作,但是该文件并没有使用我们定义的DEBUG_NEW 宏。同时用户的另一个实现文件中的代码负责调用delete 来删除前者分配的内存,但不巧的是,这个文件使用了DEBUG_DELETE 宏。这种情况下内存检测子系统会报告warning,并打印出delete 调用的文件名和行号。

3.与第二种情况相反,用户的一个实现文件调用了new 进行内存分配工作,并使用我们定义的DEBUG_NEW 宏。同时用户的另一个实现文件中的代码负责调用delete 来删除前者分配的内存,但该文件没有使用DEBUG_DELETE 宏。这种情况下,因为我们能够找到这个内存分配的原始信息,所以不会打印warning。

4.当出现嵌套delete(定义可见"实现上的问题")的情况下,以上第一和第三种情况都有可能打印出不正确的warning 信息,详细分析可见"实现上的问题"一节。

你可能觉得这样的warning 太随意了,有误导之嫌。怎么说呢?作为一个检测子系统,对待有可能的错误我们所采取的原则是:宁可误报,不可漏报。请大家"有则改之,无则加勉"。

5.动态内存泄漏信息的检测

上面我们所讲述的内存泄漏的检测能够在程序整个生命周期结束时,打印出在程序运行过程中已经在堆上分配但是没有释放的内存分配信息,程序员可以由此找到程序中"显式"的内存泄漏点并加以改正。但是如果程序在结束之前能够将自己所分配的所有内存都释放掉,是不是就可以说这个程序不存在内存泄漏呢?答案:否!在编程实践中,我们发现了另外两种危害性更大的"隐式"内存泄漏,其表现就是在程序退出时,没有任何内存泄漏的现象,但是在程序运行过程中,内存占用量却不断增加,直到使整个系统崩溃。

1.程序的一个线程不断分配内存,并将指向内存的指针保存在一个数据存储中(如list),但是在程序运行过程中,一直没有任何线程进行内存释放。当程序退出的时候,该数据存储中的指针值所指向的内存块被依次释放。

2.程序的N个线程进行内存分配,并将指针传递给一个数据存储,由M个线程从数据存储进行数据处理和内存释放。由于N 远大于M,或者M个线程数据处理的时间过长,导致内存分配的速度远大于内存被释放的速度。但是在程序退出的时候,数据存储中的指针值所指向的内存块被依次释放。

之所以说他危害性更大,是因为很不容易这种问题找出来,程序可能连续运行几个十几个小时没有问题,从而通过了不严密的系统测试。但是如果在实际环境中7×24 小时运行,系统将不定时的崩溃,而且崩溃的原因从log 和程序表象上都查不出原因。

为了将这种问题也挑落马下,我们增加了一个动态检测模块MemSnapShot,用于在程序运行过程中,每隔一定的时间间隔就对程序当前的内存总使用情况和内存分配情况进行统计,以使用户能够对程序的动态内存分配状况进行监视。

当客户使用MemSnapShot 进程监视一个运行中的进程时,被监视进程的内存子系统将把内存分配和释放的信息实时传送给MemSnapShot。MemSnapShot 则每隔一定的时间间隔就对所接收到的信息进行统计,计算该进程总的内存使用量,同时以调用new进行内存分配的文件名和行号为索引值,计算每个内存分配动作所分配而未释放的内存总量。这样一来,如果在连续多个时间间隔的统计结果中,如果某文件的某行所分配的内存总量不断增长而始终没有到达一个平衡点甚至回落,那它一定是我们上面所说到的两种问题之一。

在实现上,内存检测子系统的全局对象(appMemory)的构造函数中以自己的当前PID 为基础key 值创建一个消息队列,并在operator new 和operator delete 被调用的时候将相应的信息写入消息队列。MemSnapShot 进程启动时需要输入被检测进程的PID,而后通过该PID 组装key 值并找到被检测进程创建的消息队列,并开始读入消息队列中的数据进行分析统计。当得到operator new 的信息时,记录内存分配信息,当收到operator delete 消息时,删除相应的内存分配信息。同时启动一个分析线程,每隔一定的时间间隔就计算一下当前的以分配而尚未释放的内存信息,并以内存的分配位置为关键字进行统计,查看在同一位置(相同文件名和行号)所分配的内存总量和其占进程总内存量的百分比。

图4 是一个正在运行的MemSnapShot 程序,它所监视的进程的动态内存分配情况如图所示:

图四

在支持MemSnapShot 过程中的实现上的唯一技巧是--对于被检测进程异常退出状况的处理。因为被检测进程中的内存检测子系统创建了用于进程间传输数据的消息队列,它是一个核心资源,其生命周期与内核相同,一旦创建,除非显式的进行删除或系统重启,否则将不被释放。

不错,我们可以在内存检测子系统中的全局对象(appMemory)的析构函数中完成对消息队列的删除,但是如果被检测进程非正常退出(CTRL+C,段错误崩溃等),消息队列可就没人管了。那么我们可以不可以在全局对象(appMemory)的构造函数中使用signal 系统调用注册SIGINT,SIGSEGV 等系统信号处理函数,并在处理函数中删除消息队列呢?还是不行,因为被检测进程完全有可能注册自己的对应的信号处理函数,这样就会替换我们的信号处理函数。最终我们采取的方法是利用fork 产生一个孤儿进程,并利用这个进程监视被检测进程的生存状况,如果被检测进程已经退出(无论正常退出还是异常退出),则试图删除被检测进程所创建的消息队列。下面简述其实现原理:

在全局对象(appMemory)构造函数中,创建消息队列成功以后,我们调用fork 创建一个子进程,而后该子进程再次调用fork 创建孙子进程,并退出,从而使孙子进程变为一个"孤儿"进程(之所以使用孤儿进程是因为我们需要切断被检测进程与我们创建的进程之间的信号联系)。孙子进程利用父进程(被检测进程)的全局对象(appMemory)得到其PID 和刚刚创建的消息队列的标识,并传递给调用exec 函数产生的一个新的程序映象--MemCleaner。

MemCleaner 程序仅仅调用kill(pid, 0);函数来查看被检测进程的生存状态,如果被检测进程不存在了(正常或者异常退出),则kill 函数返回非0 值,此时我们就动手清除可能存在的消息队列。

6.实现上的问题:嵌套delete

在"错误方式删除带来的问题"一节中,我们对delete operator 动了个小手术--增加了两个全局变量(DELETE_FILE,DELETE_LINE)用于记录本次delete 操作所在的文件名和行号,并且为了同步对全局变量(DELETE_FILE,DELETE_LINE)的访问,增加了一个全局的互斥锁。在一开始,我们使用的是pthread_mutex_t,但是在测试中,我们发现pthread_mutex_t 在本应用环境中的局限性。

例如如下代码:

class B {…};

class A {

public:

A() {m_pB = NULL};

A(B* pb) {m_pB = pb;};

~A()

{

if (m_pB != NULL)

行号1 delete m_pB; //这句最要命

};

private:

class B* m_pB;

……

}

int main()

{

A* pA = new A(new B);

……

行号2 delete pA;

}

在上述代码中,main 函数中的一句delete pA 我们称之为"嵌套删除",即我们delete A 对象的时候,在A对象的析构执行了另一个delete B 的动作。当用户使用我们的内存检测子系统时,delete pA 的动作应转化为以下动作:

上全局锁

全局变量(DELETE_FILE,DELETE_LINE)赋值为文件名和行号2

delete operator A

调用~A()

上全局锁

全局变量(DELETE_FILE,DELETE_LINE)赋值为文件名和行号1

delete operator B

调用~B()

返回~B()

调用operator delete B

记录全局变量(DELETE_FILE,DELETE_LINE)值1并清除全局变量

(DELETE_FILE,DELETE_LINE)值

打开全局锁

返回operator delete B

返回delete operator B

返回~A()

调用 operator delete A

记录全局变量(DELETE_FILE,DELETE_LINE)值1并清除全局变量(DELETE_FILE,DELETE_LINE)值

打开全局锁

返回operator delete A

返回 delete operator A

在这一过程中,有两个技术问题,一个是mutex 的可重入问题,一个是嵌套删除时对全局变量(DELETE_FILE,DELETE_LINE)现场保护的问题。

所谓mutex 的可重入问题,是指在同一个线程上下文中,连续对同一个mutex 调用了多次lock,然后连续调用了多次unlock。这就是说我们的应用方式要求互斥锁有如下特性:

1.要求在同一个线程上下文中,能够多次持有同一个互斥体。并且只有在同一线程上下文中调用相同次数的unlock 才能放弃对互斥体的占有。

2.对于不同线程上下文持有互斥体的企图,同一时间只有一个线程能够持有互斥体,并且只有在其释放互斥体之后,其他线程才能持有该互斥体。

Pthread_mutex_t 互斥体不具有以上特性,即使在同一上下文中,第二次调用pthread_mutex_lock 将会挂起。因此,我们必须实现出自己的互斥体。在这里我们使用semaphore 的特性实现了一个符合上述特性描述的互斥体CCommonMutex(源代码见附件)。

为了支持特性2,在这个CCommonMutex 类中,封装了一个semaphore,并在构造函数中令其资源值为1,初始值为1。当调用CCommonMutex::lock 接口时,调用sem_wait 得到semaphore,使信号量的资源为0 从而让其他调用lock 接口的线程挂起。当调用接口CCommonMutex::unlock 时,调用sem_post 使信号量资源恢复为1,让其他挂起的线程中的一个持有信号量。

同时为了支持特性1,在这个CCommonMutex 增加了对于当前线程pid 的判断和当前线程访问计数。当线程第一次调用lock 接口时,我们调用sem_wait 的同时,记录当前的Pid 到成员变量m_pid,并置访问计数为1,同一线程(m_pid == getpid())其后的多次调用将只进行计数而不挂起。当调用unlock 接口时,如果计数不为1,则只需递减访问计数,直到递减访问计数为 1 才进行清除pid、调用sem_post。(具体代码可见附件)

嵌套删除时对全局变量(DELETE_FILE,DELETE_LINE)现场保护的问题是指,上述步骤中在 A 的析构函数中调用delete m_pB 时,对全局变量(DELETE_FILE,DELETE_LINE)文件名和行号的赋值将覆盖主程序中调用delete pA 时对全局变量(DELETE_FILE,DELETE_LINE)的赋值,造成了在执行operator delete A 时,delete pA 的信息全部丢失。

要想对这些全局信息进行现场保护,最好用的就是堆栈了,在这里我们使用了STL 提供的stack 容器。在DEBUG_DELETE 宏定义中,对全局变量(DELETE_FILE,DELETE_LINE)赋值之前,我们先判断是否前面已经有人对他们赋过值了--观察行号变量是否等于0,如果不为0,则应该将已有的信息压栈(调用一个全局函数BuildStack() 将当前的全局文件名和行号数据压入一个全局堆栈globalStack),而

后再对全局变量(DELETE_FILE,DELETE_LINE)赋值,再调用delete operator。而在内存子系统的全局对象(appMemory)提供的erase 接口里面,如果判断传入的文件名和行号为0,则说明我们所需要的数据有可能被嵌套删除覆盖了,所以需要从堆栈中弹出相应的数据进行处理。

现在嵌套删除中的问题基本解决了,但是当嵌套删除与"错误方式删除带来的问题"一节的最后所描述的第一和第三种异常情况同时出现的时候,由于用户的delete 调用没有通过我们定义的

DEBUG_DELETE 宏,上述机制可能出现问题。其根本原因是我们利用stack 保留了经由我们的DEBUG_DELETE 宏记录的delete 信息的现场,以便在operator delete 和全局对象(appMemory)的erase 接口中使用,但是用户的没经过DEBUG_DELETE 宏的delete 操作却未曾进行压栈操作而直接调用了operator delete,有可能将不属于这次操作的delete 信息弹出,破坏了堆栈信息的顺序和有效性。那么,当我们因为无法找到这次及其后续的delete 操作所对应的内存分配信息的时候,可能会打印出错误的warning 信息。

展望

以上就是我们所实现的内存泄漏检测子系统的原理和技术方案,第一版的源代码在附件中,已经经过了较严格的系统测试。但是限于我们的C++ 知识水平和编程功底,在实现过程中肯定还有没有注意到的地方甚至是缺陷,希望能够得到大家的指正,我的email 是hcode@https://www.doczj.com/doc/d18628144.html,。

在我们所实现的内存检测子系统基础上,可以继续搭建内存分配优化子系统,从而形成一个完整的内存子系统。一种内存分配优化子系统的实现方案是一次性分配大块的内存,并使用特定的数据结构管理之,当内存分配请求到来时,使用特定算法从这块大内存中划定所需的一块给用户使用,而用户使用完毕,在将其划为空闲内存。这种内存优化方式将内存分配释放转换为简单的数据处理,极大的减少了内存申请和释放所耗费的时间。

LINUX中限制CPU和内存占用率方法

查看cpu占用 在命令行中输入 top 即可启动 top top 的全屏对话模式可分为3部分:系统信息栏、命令输入栏、进程列表栏。 使用top查看系统负荷 top命令可以动态监视系统负荷,包括CPU、内存的使用率和占用资源较多的进程详情等。 动态查看系统负荷(占用一个终端) top 显示后退出 top -n 1 以文本方式输出,以备其它程序使用 top -b 好了,我们现在来看限制CPU和内存占用率方法 脚本内容: 代码如下 #!/bin/sh UPID=`top -bn 1 | grep ^ *[1-9] | awk '{ if($9 ; 20 || $10 ; 25 && id -u $2 ; 500) print $1}'` for PID in $UPID do renice +10 $PID echo renice +10 $PID done

我对上面的脚本进行了修改,可以让其针对整个服务器的进程进行限制. 修改后的脚本: 代码如下 #!/bin/sh UPID=`top -bn 1 | grep ^ *[1-9] | awk '{ if($9 ; 50 || $10 ; 25 ) print $1}'` for PID in $UPID do renice +10 $PID echo renice +10 $PID done 可以将这个脚本放到cron中运行,让其每分钟检查一次: 代码如下 chmod +x limit.sh vi /etc/crontab */1 * * * * /bin/sh /root/soft_shell/limit.sh

内存检测工具的使用教程

u启动WINDIAG内存检测工具的使用教程 按下回车将后,电脑会自动进行内存的检测,直到您按下“X”键或者是关闭电脑 windiag内存检测工具将会自动运行,在这里它会无限进行电脑内存检测,我们只要关注工具进行test5次以上检测即可,检测结果会显示在“results”和“pass”以及“cache”这三个位置在电脑检测内存的过程中,我们也可以看到检测是否成功和检测的进度; 上述过程就是如何运用U盘启动盘的内存检测WINDIAG工具对电脑内存进行检测。用户需要注意的是,WINDIAG工具会无限次循环检测内存,我们只需检测次数达到5次以上,按下“X”键或直接关闭电脑。******************************************************************************* u启动Memtest4.20内存检测工具使用教程 当我们按下回车键时系统便会自动进行内存检测,检测的时间大约会在2小时左右,请耐心等待。

现在u启动小编就内存检测的过程中的相关数值向大家详细说明一下: 上方的Pass:表示检测过程中的整体进度; Test:表示检测当前进度; 下方的WallTime:检测时长,大约会在2小时左右; Pass:进行内存检测的次数,经过这一次检测后,下次检测时这里的数值将会是“1”,并且每一次的检测都会累计上去。 Error ECC Errs:检测错误的次数和地点将会在此显示出来。 ******************************************************************************* u启动u盘启动物理内存检测memtest使用教程 物理内存检测memtest是一款可以对电脑内存进行精确检测的工具,在使用时需要关闭当前电脑中所有正在运行的程序,在进行测试时,建议至少运行20分钟,您运行的时间越长,结果越准确。如果拥有多个核心/处理器,可以运行多个副本MemTest分别测试它们之间的内存大小。下面就来看看如何使用这款工具吧。 首先,制作一个u启动u盘启动盘,我们可以从u启动官网下载u启动u盘启动盘制作工具制作一个启动u盘,具体可以参考“下载并安装u启动v6.1制作u盘启动盘教程”。 1、把制作好的u启动u盘启动盘插在电脑usb接口上,然后重启电脑,在出现开机画面时 用一键u盘启动快捷键的方法进入到启动项选择窗口,选择u盘启动,进入到u启动v6.1主菜单界面,选择【02】运行u启动win8pe防蓝屏(新机器)选项,按回车键确认选择,如下图所示:

linux查看内存和CPU详解

Linux的缓存机制:Linux会针对dentry(用于VFS,加速文件路径名到inode的转换)、Buffer Cache(针对磁盘块的读写)和Page Cache(针对文件inode的读写)进行缓存操作。 操作步骤: 1、查询当前内存使用情况和释放缓存的参数 #free -m #cat /proc/sys/vm/drop_caches 2、使用sync命令,将系统缓存区中的脏数据写入磁盘中,包括已修改的i-node、已延迟的块I/O和读写映射文件。 #sync 3、配置文件/proc/sys/vm/drop_caches中记录了缓存释放的参数,含义:默认0—不释放,1—释放pagecache,2—释放dentries和inodes,3—释放所有缓存 #echo 3 > /proc/sys/vm/drop_caches echo 3 > /proc/sys/vm/drop_caches total——总物理内存 used——已使用内存,一般情况这个值会比较大,因为这个值包括了cache+应用程序使用的内存 free——完全未被使用的内存 shared——应用程序共享内存 buffers——缓存,主要用于目录方面,inode值等(ls大目录可看到这个值增加)cached——缓存,用于已打开的文件 note: Tasks: 150 total 进程总数 2 running 正在运行的进程数 148 sleeping 睡眠的进程数 0 stopped 停止的进程数 0 zombie 僵尸进程数 Cpu0: 67.4% us 用户空间占用CPU百分比 2.0% sy 内核空间占用CPU百分比 0.0% ni 用户进程空间内改变过优先级的进程占用CPU百分比 30.2% id 空闲CPU百分比 0.0% wa 等待输入输出的CPU时间百分比 0.0% hi 0.0% si 0.0% st cpu 统计信息区域的下方显示了各个进程的详细信息。首先来认识一下各列的含义。 序号列名含义 a PID 进程id

Linux下使用cpulimit限制进程的cpu使用率

Linux下使用cpulimit限制进程的cpu使用率 很用Linux时可能大家经常发现莫名其妙就变的非常慢,这时多半是后台进程使用的cpu和内存太多了。如何限制每个进程的cpu使用资源呢? 可以使用cpulimit限制每个进程的cpu使用率,使用率用百分百来表示。 安装cpulimit 使用源码安装 # cd /tmp # wget '网址http://' 网址:https://www.doczj.com/doc/d18628144.html,/cpulimit/cpulimit-1.1.tar.gz # tar cpulimit-1.1.tar.gz # cd cpulimit-1.1 # make # cp cpulimit /usr/local/sbin/ # rm -rf cpulimit* Debian / Ubuntu 用户 使用apt-get更方便的安装 $ sudo apt - get update $ sudo apt - get install cpulimit 如何使用cpulimit? 限制firefox使用30% cpu利用率 # cpulimit -e firefox -l 30 限制进程号1313的程序使用30% cpu利用率 # cpulimit -p 1313 -l 30 根据进程名找出pid的方法 # ps aux | less # ps aux | grep firefox # pgrep -u vivek php-cgi # pgrep lighttpd 可以使用绝对路径限制进程的cpu利用率 # cpulimit -P /opt/firefox/firebox -l 30 单核cpu和多核cpu 单核cpu的使用率范围为0%-100%,四核cpu的使用率范围为0%-400%.

linux如何查看CPU,内存,机器型号,网卡信息

linux如何查看CPU,内存,机器型号,网卡信息 查看CPU信息(型号) # cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c 8 Intel(R) Xeon(R) CPU E5410 @ 2.33GHz (看到有8个逻辑CPU, 也知道了CPU型号) # cat /proc/cpuinfo | grep physical | uniq -c 4 physical id : 0 4 physical id : 1 (说明实际上是两颗4核的CPU) PS:Jay added on 10th, May, 2011 # 其实是可能有超线程HT技术,不一定是有4核,也可能是2核4线程;当时还理解不清楚 # getconf LONG_BIT 32 (说明当前CPU运行在32bit模式下, 但不代表CPU不支持64bit) # cat /proc/cpuinfo | grep flags | grep ' lm ' | wc -l 8 (结果大于0, 说明支持64bit计算. lm指long mode, 支持lm则是64bit) 再完整看cpu详细信息, 不过大部分我们都不关心而已. # dmidecode | grep -A81 'Processor Information' 查看主板型号: # dmidecode |grep -A16 "System Information$" 内存槽及内存条: # dmidecode |grep -A16 "Memory Device$" 查看内存信息 # cat /proc/meminfo # uname -a Linux euis1 2.6.9-55.ELsmp #1 SMP Fri Apr 20 17:03:35 EDT 2007 i686 i686 i386 GNU/Linux (查看当前操作系统内核信息) # cat /etc/issue | grep Linux Red Hat Enterprise Linux AS release 4 (Nahant Update 5) (查看当前操作系统发行版信息)

linux c程序获取cpu使用率及内存使用情况

想获取一下目标机运行时linux系统的硬件占用情况,写了这几个小程序,以后直接用了。方法就是读取proc下的文件来获取了。cpu使用率:/proc/stat ,内存使用情 况:/proc/meminfo 看程序: /*************************************************************** * @file: statusinfo.c * * @brief: 从linux系统获取cpu及内存使用情况 * * @version 1.0 * * @author 抹黑 * * @date 2009年3月17日 * ***************************************************************/ typedef struct PACKED //定义一个cpu occupy的结构体 { char name[20]; //定义一个char类型的数组名name有20个元素 unsigned int user; //定义一个无符号的int类型的user unsigned int nice; //定义一个无符号的int类型的nice unsigned int system;//定义一个无符号的int类型的system unsigned int idle; //定义一个无符号的int类型的idle }CPU_OCCUPY; typedef struct PACKED //定义一个mem occupy的结构体 { char name[20]; //定义一个char类型的数组名name有20个元素 unsigned long total; char name2[20]; unsigned long free; }MEM_OCCUPY; get_memoccupy (MEM_OCCUPY *mem) //对无类型get函数含有一个形参结构体类弄的指针O

Linux查看CPU和内存使用情况

Linux 查看CPU 和内存使用情况 在系统维护的过程中,随时可能有需要查看CPU 使用率,并根据相应信息分析系统状况的需要。在CentOS 中 可以通过top 命令来查看CPU 使用状况。运行top 命令后,CPU 使用状态会以全屏的方式显示,并且会处在对话的模式-- 用基于top 的命令,可以控制显示方式等等。退出 top 的命令为q (在top 运行中敲q 键一次)。 top 命令是Linux 下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows 的任务管理器 可以直接使用top 命令后,查看%MEM 的内容。可以选 择按进程查看或者按用户查看,如想查看oracle 用户的进程内存使用情况的话可以使用如下的命令: $ top -u oracle 内容解释: PID :进程的ID USER :进程所有者 PR:进程的优先级别,越小越优先被执行 NInice :值 VIRT :进程占用的虚拟内存 RES:进程占用的物理内存

SHR :进程使用的共享内存 僵死状态, N 表示该进程优先值为负数 %CPU :进程占用CPU 的使用率 %MEM :进程使用的物理内存和总内存的百分比 TIME+ :该进程启动后占用的总的 CPU 时间,即占用 CPU 使用时间的累加值。 COMMAND :进程启动命令名称 操作实例 : 即可启动 top top 的全屏对话模式可分为 3 部分:系统信息栏、命令 输入栏、进程列表栏。 第一部分 -- 最上部的 系统信息栏 第一行( top ): 00:11:04”为系统当前时刻; 3:35”为系统启动后到现在的运作时间; “2 users ”为当前登录到系统的用户,更确切的说 是登录到用户的终端数 -- 同一个用户同一时间对系统多个 终端的连接将被视为多个用户连接到系统,这里的用户数也 将表现为终端的数目; S :进程的状态。 S 表示休眠, R 表示正在运行, Z 表示 在命令行中输入 “- ” top ”

微软极品Sysinternals Suite工具包使用指南

微软极品Sysinternals Suite工具包使用指南 2010-6-26 10:00:13 编辑:软媒- 笨笨人气:11430次评论(8) Windows7之家(https://www.doczj.com/doc/d18628144.html,):微软极品Sysinternals Suite工具包使用指南 为什么软媒小编把Sysinternals Suite冠以极品二字?其实从07年Vista之家开始运行的时候,就推荐过这套软件10几次。被微软官方收购的这套软件包,确实有强悍的过人之处,软媒在开发魔方和Windows7优化大师的时候,也借鉴学习了这套软件的很多功能和思想。 今天,软媒小编把这套工具包里面的每个实用软件都整理出来,按照名称首字母排序,点击每个蓝色标题链接都可以转到微软的对应官方页面,有对这些工具包的直接下载地址和更详尽的用法。因为每个软件几乎都可以长篇大论的介绍,所以,在此就只做简介和罗列,希望能够对大家有所帮助。 每个软件都可以单独下载,当然更建议直接下载他们的集成版——Sysinternals Suite 系统工具套装。其实,这套工具包的下载地址几乎是常年不变的,基本都保持在10M大小,下载地址大家可以记住:https://www.doczj.com/doc/d18628144.html,/Files/SysinternalsSuite.zip。 好吧,下面是列表,都是中文说明。 一、各工具简介和微软官方网页 AccessChk 为了确保创建安全的环境,Windows 管理员通常需要了解特定用户或用户组对文件、目录、注册表项和Windows 服务等资源具有哪种访问权限。AccessChk 能够通过直观的界面和输出快速回答这些问题。 AccessEnum 这一简单但强大的安全工具可以向您显示,谁可以用何种访问权限访问您系统中的目录、文件和注册表项。使用此工具可查找权限漏洞。 AdExplorer Active Directory Explorer 是一个高级的Active Directory (AD) 查看器和编辑器。

Linux查看CPU和内存使用情况

Linux查看CPU和内存使用情况 在系统维护的过程中,随时可能有需要查看CPU 使用率,并根据相应信息分析系统状况的需要。在Ce ntOS 中,可以通过top 命令来查看CPU 使用状况。运行top 命令后,CPU 使用状态会以全屏的方式显示,并且会处在对话的模式-- 用基于top 的命令,可以控制显示方式等等。退出top 的命令为q (在top 运行中敲q 键一次)。 操作实例: 在命令行中输入“top” 即可启动top top 的全屏对话模式可分为3部分:系统信息栏、命令输入栏、进程列表栏。 第一部分-- 最上部的系统信息栏: 第一行(top): “00:11:04”为系统当前时刻; “3:35”为系统启动后到现在的运作时间; “2 users”为当前登录到系统的用户,更确切的说是登录到用户的终端数-- 同一个用户同一时间对系统多个终端的连接将被视为多个用户连接到系统,这里的用户数也将表现为终端的数目; “load average”为当前系统负载的平均值,后面的三个值分别为1分钟前、5分钟前、15分钟前进程的平均数,一般的可以认为这个数值超过CPU 数目时,CPU 将比较吃力的负载当前系统所包含的进程; 第二行(Tasks): “59 total”为当前系统进程总数; “1 running”为当前运行中的进程数; “58 sleeping”为当前处于等待状态中的进程数; “0 stoped”为被停止的系统进程数; “0 zombie”为被复原的进程数; 第三行(Cpus): 分别表示了CPU 当前的使用率; 第四行(Mem): 分别表示了内存总量、当前使用量、空闲内存量、以及缓冲使用中的内存量; 第五行(Swap): 表示类别同第四行(Mem),但此处反映着交换分区(Swap)的使用情况。通常,交换分区(S wap)被频繁使用的情况,将被视作物理内存不足而造成的。 第二部分-- 中间部分的内部命令提示栏: top 运行中可以通过top 的内部命令对进程的显示方式进行控制。内部命令如下表: s - 改变画面更新频率 l - 关闭或开启第一部分第一行top 信息的表示

在Linux系统中使用w命令和uptime命令查看系统负载

在Linux系统中使用w命令和uptime命令查看系统负载 在Linux系统中查询系统CPU和内存的负载(使用率)时,我们通常习惯于使用top或者atop命令,这篇文章将要给大家介绍如何使用w命令和uptime命令来查看系统的负载情况,对于uptime命令,相信大家比较熟悉了,它主要是用来查询系统最近一次启动后运行了多长时间,而w命令则相对就冷门一些了,下面就详细介绍如何使用这两个命令: 1. w命令 [root@tektea ~]# w 14:44:27 up 62 days, 3 min, 2 users, load average: 0.00, 0.01, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 218.18.74.196 13:38 1:01m 0.00s 0.00s -bash root pts/1 218.18.74.196 14:43 0.00s 0.00s 0.00s w 使用man w查询的Linux对该命令的介绍是“Show who is logged on and what they are doing.”,w命令可查询登录当前系统的用户信息,以及这些用户目前正在做什么操作,这些信息对于Linux系统管理员来说都是价值的,另外其中的load average后面的三个数字则显示了系统最近1分钟、5分钟、15分钟的系统平均负载情况。 2. uptime命令 [root@tektea ~]# uptime 14:51:15 up 62 days, 10 min, 2 users, load average: 0.02, 0.01, 0.00 uptime命令回显中的load average所表示的意思和w命令相似,都是表示过去的1分钟、5分钟和15分钟内进程队列中的平均进程数量。 这里需要注意的是load average这个输出值,这三个值的大小一般不能大于系统逻辑CPU的个数,例如,本输出中系统有4个逻辑CPU,如果load average的三个值长期大于4时,说明CPU很繁忙,负载很高,可能会影响系统性能,但是偶尔大于4时,倒不用担心,一般不会影响系统性能。相反,如果load average的输出值小于CPU的个数,则表示CPU还有空闲,比如本例中的输出,CPU是比较空闲的。

三种优秀的内存测试软件用法

(二)RAM Stress Test(RST)内存测试软件 Data Bus 数据总线 工厂检测内存条质量的软件Ram Stress Test,只要有一丁点问题,都能检查出来,推荐大家使用,各位一定都碰到过,提示内存不能为READ,或者WRITTEN的情况,很多时候都是软件问题,要解决他首先检查内存条的质量,然后再从软件去找问题。这个软件是最专业的,比那个MEMREST还好,只需要检查一边,好就是好,坏的就是坏的。这个软件确实很好,内存坏的话会显示红色,并且报警。但是只能检测一代内存,二代内存就需要微软的检测工具了。Ram Stress Test是美国Ultra-X公司旗下的一个专业记忆体测试程式,是专门给系统生产厂商出机前用的测试程式,他其实是从其他的产品独 过他的测试几乎就能应付大部分的记忆体问题,所以是非常好用的一个测试工具!! 使用非常简易,只要设定为软碟开机就行了,他是一个独立开发的系统,没有依附任何作业系统,相容于x86系列,只要BIOS认的到的容量他都能测!!发现ATS 选项错误,在BIOS 中,记忆体选项设成Auto时,记忆体的CL=2,改成Manual,自设CL=时,上述选项才能通过。 程序执行后,第一选项是测试物理内存中基本内存地址(<640K),第二项是扩展内存地址,第三项是测试你CPU的L2 cache。 ☆可以测试SD及DDR内存。 ☆ 依次代表内存条的8颗颗粒。

从左到右横着数:0-7代表第1颗粒区域、8-F代表第2颗粒、0-7代表第3颗粒、8-F代表第4颗粒、0-7代表第5颗粒代、8-F代表第6颗粒、0-7代表 第7颗粒、8-F代表第8颗粒 ☆点不亮内存的测试方法——很多内存短路或者颗粒损坏后都不能点亮,点不亮的可以用一根好的内存去带动它(可解决部分点不亮问题) 。必须SD的带SD的,DDR的带DDR的。本软件会自动跳过好的去检测坏的那根。 ☆发现ATS 选项错误,在BIOS中,记忆体选项设成Auto时,记忆体的CL=2,改成Manual,自设CL=时,上述选项才能通过。 ☆程序执行后,第一选项是测试物理内存中基本内存地址(<640K),第二项是扩展内存地址,第三项是测试CPU的L2 cache。 RAM测试软件说明书 )UX版 闪动的一排测试数字代表内存8颗粒的测试情况。 从左至右,0-7代表第一区域,8-F代表第二区域;0-7代表第三区域,8-F代表第四区域;……依次代表内存条的8颗颗粒。 ⒈DDR8位与16位的单面测法: ⑴. 0-7(1 )区域如果出现乱码,代表这根DDR内存条的第1颗粒已经损坏 ⑵. 8-F(2 )区域如果出现乱码,代表这根DDR内存条的第2颗粒已经损坏 ⑶. 0-7(3 )区域如果出现乱码,代表这根DDR内存条的第3颗粒已经损坏 ⑷. 8-F(4 )区域如果出现乱码,代表这根DDR内存条的第4颗粒已经损坏 ⑸. 0-7(5 )区域如果出现乱码,代表这根DDR内存条的第5颗粒已经损坏 ⑹. 8-F(6 )区域如果出现乱码,代表这根DDR内存条的第6颗粒已经损坏 ⑺. 0-7(7 )区域如果出现乱码,代表这根DDR内存条的第7颗粒已经损坏 ⑻. 8-F(8 )区域如果出现乱码,代表这根DDR内存条的第8颗粒已经损坏 注意DR的颗粒排列循序是-8 ⒉如果你是128M的双面DDR内存,如以上显示界面图: 1-16M ------------------------------------------------------------------------------------------------------------ 16-32M ------------------------------------------------------------------------------------------------------- 32-48M ------------------------------------------------------------------------------------------------------------ 48-64M------------------------------------------------------------------------------------------------------------- 从1M到64M的上面的4根虚线上出现乱码的话,说明这根内存的的第一面的颗粒有问题(判断哪个颗粒的好坏按照以上的说明) 64-80M ------------------------------------------------------------------------------------------------------------ 80-96M ------------------------------------------------------------------------------------------------------- 96-112M------------------------------------------------------------------------------------------------------------ 112-128M---------------------------------------------------------------------------------------------------------- 从64M到128M的上面的4根虚线上出现乱码的话,说明这根内存的的第二面的颗粒有问题(判断哪个颗粒的好坏按照以上的说明) 注意:在内存的PCB板上的两边标着1与92的代表第一面,93与184的代表第二面。1-128M 的8根虚线是用来区分两面区域的作用. ⒊SD的8位与16位的单面测法: ⑴. 0-7(1)区域如果出现乱码,代表这根SDR内存条的第8颗粒已经损坏 ⑵. 8-F(2)区域如果出现乱码,代表这根SDR内存条的第4颗粒已经损坏 ⑶. 0-7(3)区域如果出现乱码,代表这根SDR内存条的第7颗粒已经损坏 ⑷. 8-F(4)区域如果出现乱码,代表这根SDR内存条的第3颗粒已经损坏 ⑸. 0-7(5)区域如果出现乱码,代表这根SDR内存条的第6颗粒已经损坏

微软 软件测试

微软的测试 “很多人都认为微软是一家软件开发公司, 而事实上,我们是一家软件测试公司”。

?微软的软件测试80%-90%都是自动化的。(所谓自动化,就是由测试工程师写出测试程序来运行测试 案例,而并非人们所想象的人工点、点、点的那种测试 方式。) ?每个产品的测试都包含了基本的测试,如功能测试、压力测试、代码覆盖率校验、插入测试、与其他产品交互的测试,还有全球化和本地化测试。在测试用例上,几乎永远是越多越全面越好。

?测试Windows XP操作系统某项目时,仅对几个DLL文件的测试就写了两千多个测试用例。 ?微软的测试工具基本上都是自己开发的,虽然商业性比较差,但对产品的针对性很强。除了常用的十种左右的测试工具外,往往需要测试人员针对项目开发很多测试工具。

一、微软的测试人员 微软的软件测试人员分为两类: 1.测试工具软件开发工程师(SDE/T) Software Development Engineer in Test:负责写测试工具代码,并利用 测试工具对软件进行测试;或者开发测试工具为软件测试工程师服务。产品开发后的性能测试(Performance Test)、提交测试(Check-in Test)等 过程,都有可能要用到SDE/T 开发的测试工具。 由于SDE/T和SDE 的工作都是写代码,具有相通的地方,所以两者之间互相转换的情况比较多。但需注意的是,两者写出来的代码用途是不一样的,SDE 写的是产品的代码,而SDE/T 写的代码只用于测试产品。 2.软件测试工程师(STE) Software Test Engineer:负责理解产品的功能要求,然后对其进行测试,检查软件有没有错误(Bug),决定软件是否具有稳定性,并写出相

linux下如何获取cpu的利用率

linux下如何获取cpu的利用率 “proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程序可以通过proc 得到系统的信息,并可以改变内核的某些参数。” 这里将介绍如何从/proc文件系统中获取与防火墙相关的一些性能参数,以及如何通过/proc 文件系统修改内核的相关配置。 1、从/proc文件系统获取相关的性能参数 cpu使用率:/proc/stat 内存使用情况:/proc/meminfo 网络负载信息:/proc/net/dev 相应的计算方法:(摘自:什么是proc文件系统,见参考资料) (1)处理器使用率 (2)内存使用率 (3)流入流出数据包 (4)整体网络负载 这些数据分别要从/proc/stat、/proc/net/dev、/proc/meminfo三个文件中提取。如里有问题或对要提取的数据不太清楚,可以使用man proc来查看proc文件系统的联机手册。 (1)处理器使用率 这里要从/proc/stat中提取四个数据:用户模式(user)、低优先级的用户模式(nice)、内核模式(system)以及空闲的处理器时间(idle)。它们均位于/proc/stat文件的第一行。CPU 的利用率使用如下公式来计算。 CPU利用率= 100 *(user + nice + system)/(user + nice + system + idle) (2)内存使用率 这里需要从/proc/meminfo文件中提取两个数据,当前内存的使用量(cmem)以及内存总量(amem)。

microsoftoffice诊断的结果

microsoftoffice诊断的结果 Microsoft Office 诊断的结果本页介绍您刚刚运行的Microsoft Office 诊断的结果。您还可能会看到有关如何提高计算机和2007 Microsoft Office system 安装运行状况的建议。 注释可以将此页打印出来或标记为书签以供将来参考,这将十分有用。 诊断结果 Microsoft Office 诊断未发现任何问题。 安装程序诊断—文件损坏或文件被更改 安装程序诊断修复了Microsoft Office 安装的问题。现在您的Microsoft Office 程序应该可以正常工作。 如果Microsoft Office 程序仍然会崩溃,则问题的根源可能是硬件故障或硬件配置问题。请查看磁盘和内存诊断的结果,以确定是否是硬件故障影响了 2007 Office 版本的安装。 安装程序诊断—缺少媒体 安装程序诊断由于未找到有效的源媒体而未能完成。可能缺少本地安装源,或者用于安装Microsoft Office

的原始源媒体对于修复过程不可用。您可能需要提供原始源媒体,此诊断测试才能成功运行。2007 Office 版本的有效源媒体包括: 2007 Office 版本安装CD 计算机供应商提供的安装盘或修复CD 与2007 Office 版本网络安装点的连接 在获得对有效源媒体的访问后,请再次运行Office 诊断。 磁盘诊断—预测到硬盘故障 硬盘的自监控、分析与报告技术(SMART) 功能已发现错误,指示硬盘可能要出现故障。SMART 是某些磁盘驱动器制造商提供的一种功能,可以预先通知用户硬盘存在潜在故障。Microsoft Office 程序不稳定可能是由这些硬盘驱动器错误引起的。 注释此结果可能表示存在严重问题,但某些硬盘可能会不准确地报告结果。 建议您执行下列操作: 立即备份您的重要数据。 检查其他诊断的结果,并按照说明进行操作来解决其他诊断报告的任何问题。解决了这些问题后,再次运行Microsoft

Java获取Linux和Window系统CPU、内存和磁盘总使用率的情况

本文由我司收集整编,推荐下载,如有疑问,请与我司联系Java 获取Linux 和Window 系统CPU、内存和磁盘总使用率的情况 2017/05/08 0 这是一个工具类,获取的内容: CPU 使用率:得到的是当前CPU 的使用情况,这是算出的是两次500 毫秒时间 差的CPU 使用率 内存使用率:[1 - 剩余的物理内存/(总的物理内存+虚拟内存) ] * 100 磁盘总使用率:[1 - 磁盘空余大小/磁盘总大小] * 100 下面开始贴代码:使用暂时没有发现什么问题,如果有问题,咱们可以一起讨论package com.util; import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStreamReader;import java.io.LineNumberReader;import https://www.doczj.com/doc/d18628144.html,ng.management.ManagementFactory;import java.math.BigDecimal;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.StringTokenizer; import org.apache.log4j.Logger; import com.sun.management.OperatingSystemMXBean; public class ComputerMonitorUtil { private static String osName = System.getProperty(“https://www.doczj.com/doc/d18628144.html,”);private static final int CPUTIME = 500;private static final int PERCENT = 100;private static final int FAULTLENGTH = 10;private static final Logger logger = Logger.getLogger(ComputerMonitorUtil.class); /** * 功能:获取Linux 和Window 系统cpu 使用率* */public static double getCpuUsage() {// 如果是window 系统if (osName.toLowerCase().contains(“windows”)||osName.toLowerCase().contains(“win”)) {try {String procCmd = System.getenv(“windir”)+“//system32//wbem//wmic.exe process get Caption,CommandLine,KernelModeTime,ReadOperationCount,ThreadCount,UserModeTi

内存泄露检测工具

1. ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。 2. Dmalloc-Debug Malloc Library. 3. Electric Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。 4. Leaky-Linux下检测内存泄漏的程序。 5. LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。 6. MEMWA TCH-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。 7. V algrind-Debugging and profiling Linux programs, aiming at programs written in C and C++. 8. KCachegrind-A visualization tool for the profiling data generated by Cachegrind and Calltree. 9. Leak Monitor-一个Firefox扩展,能找出跟Firefox相关的泄漏类型。 10. IE Leak Detector (Drip/IE Sieve)-Drip和IE Sieve leak detectors帮助网页开发员提升动态网页性能通过报告可避免的因为IE局限的内存泄漏。 11. Windows Leaks Detector-探测任何Win32应用程序中的任何资源泄漏(内存,句柄等),基于Win API调用钩子。 12. SAP Memory Analyzer-是一款开源的JA V A内存分析软件,可用于辅助查找JA V A程序的内存泄漏,能容易找到大块内存并验证谁在一直占用它,它是基于Eclipse RCP(Rich Client Platform),可以下载RCP的独立版本或者Eclipse的插件。 13. DTrace-即动态跟踪Dynamic Tracing,是一款开源软件,能在Unix类似平台运行,用户能够动态检测操作系统内核和用户进程,以更精确地掌握系统的资源使用状况,提高系统性能,减少支持成本,并进行有效的调节。 14. IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管.NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus 将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。 15. Parasoft Insure++-针对C/C++应用的运行时错误自动检测工具,它能够自动监测C/C++程序,发现其中存在着的内存破坏、内存泄漏、指针错误和I/O等错误。并通过使用一系列独特的技术(SCI技术和变异测试等),彻底的检查和测试我们的代码,精确定位错误的准确位置并给出详细的诊断信息。能作为Microsoft V isual C++的一个插件运行。

linux系统下查看系统信息命令

Linux的文件系统中,有一个特殊目录“/proc”,该目录下列出的文件并非保存在磁盘上,而是内存中的一个映像。在该目录下可以找到许多有意思的东西,例如: /proc/cpuinfo 本机CPU的相关信息; /proc/meminfo 本机内存及交换分区的使用信息; /proc/modules 本机已安装的硬件模块信息; /proc/mounts 本机已挂载mount 上的设备信息; 此外,该目录下有一些以数字为名称的子目录,每个子目录用于维护一个正在运行的进程,而目录名即为相应的进程ID。例如进入名称为“1” 的子目录:cd /proc/1 该目录下文件“cmdline” 中的内容为该进程运行时执行的命令行;“environ”文件中的内容为该进程运行时的环境变量信息;“stat” 文件中存放的时该进程运行的状态信息等。 通过查看“ /proc” 目录下的文件,可以获取几乎所有的系统信息及系统的运行状态信息。事实上,Linux下的诸多查询系统状态信息的命令,也是通过读取该目录下的文件而获取的。 以下是一些用于查看系统状态信息的命令: df 命令 用于查看Linux 文件系统的状态信息,显示各个分区的容量、已使用量、未使用量及挂载点等信息。如: df -k 以千字节(KB)为单位显示各分区的信息; df -a 显示所有分区,包括大小为0 的分区; df -T 显示分区类型(EXT2 或EXT3等)。 du 命令 用于查看文件或文件夹的大小。如: du -b /home 以字节为单位显示“ /home ”文件夹下各个子文件夹的大小; du -ks home 以千字节(KB)为单位显示“/home” 文件夹的总大小; top 命令(第三页有详细的图形介绍top命令) 用于实时查看系统状态信息。运行该命令后,屏幕上会显示如下信息: CPU状态(CPU states):包括用户进程占用比率、系统进程占用比率、用户的nice 优先级进程占用比率及空闲CPU资源比率等;

LINUX下查看CPU使用率的命令

LINUX下查看CPU使用率的命令 1.top 使用权限:所有使用者 使用方式:top [-] [d delay] [q] [c] [S] [s] [i] [n] [b] 说明:即时显示process的动态 d :改变显示的更新速度,或是在交谈式指令列( interactiv e command)按s q :没有任何延迟的显示速度,如果使用者是有superuser的权限,则top将会以最高的优先序执行 c :切换显示模式,共有两种模式,一是只显示执行档的名称,另一种是显示完整的路径与名称S :累积模式,会将己完成或消失的子行程( dea d child process )的CPU time累积起来 s :安全模式,将交谈式指令取消,避免潜在的危机 i :不显示任何闲置(idle)或无用(zombie)的行程 n :更新的次数,完成后将会退出top b :批次档模式,搭配"n"参数一起使用,可以用来将top的结果输出到档案内 范例: 显示更新十次后退出; top -n 10 使用者将不能利用交谈式指令来对行程下命令: top -s

将更新显示二次的结果输入到名称为top.log的档案里: top -n 2 -b < top.log 另附一个命令简介linux traceroutewindows tracert两个命令相当,跟踪网络路由 2.vmstat 正如我们之前讨论的任何系统的性能比较都是基于基线的,并且监控CPU的性能就是以上3点,运行队列、CPU使用率和上下文切换。以下是一些对于CPU很普遍的性能要求: 1.对于每一个CPU来说运行队列不要超过3,例如,如果是双核CPU就不要超过6; 2.如果CPU在满负荷运行,应该符合下列分布, a) User Time:65%~70% b) System Time:30%~35% c) Idle:0%~5% 3. mpstat 对于上下文切换要结合CPU使用率来看,如果CPU使用满足上述分布,大量的上下文切换也是可以接受的。 常用的监视工具有:vmstat, top,dstat和mpstat. # vmstat 1 procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa 0 0 104300 16800 95328 72200 0 0 5 26 7 14 4 1 95 0 0 0 104300 16800 95328 72200 0 0 0 24 1021 64 1 1 98 0 0 0 104300 16800 95328 72200 0 0 0 0 1009 59 1 1 98 0 r表示运行队列的大小,

相关主题
文本预览
相关文档 最新文档