内存碎片处理(100分)

  • 主题发起人 主题发起人 行人-乙
  • 开始时间 开始时间

行人-乙

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大虾
怎么处理内存碎片啊
 
一般不直接操作内存.
 
电脑启动一段时间后,因为运行了很多程序,整台电脑速度会越来越慢.为什么呢?原来很多程序运行的时候需要占用很多内存.即使程序退出后仍然无法完全释放的.那么如何找回丢失的内存呢?现在有很多这类程序,比如说<<Windows优化大师>>就带了一个<<Windows内存整理>>工具.我手头上的是V1.1版本.
程序设计会写代码很重要.程序设计思路更重要.程序设计分析别人的思路然后归自己所有更更重要.我希望通过这篇文章让大家掌握如何分析别人的思路,这样比单纯公布思路有价值的多.
先把话题扯远一点.木马冰河大家应该听说过吧.它的配置就很值得我们学习.一般这类软件的原理是这样的:客户端程序把信息写进服务端,服务端第一次运行的时候从自己身上读取出来保存到注册表或者INI文件里面.这样做的好处在于方便远程更新的时候直接修改注册表即可.这样做也有个致命BUG,就是别人用注册表监视器之类很容易就发现,这样一来别人就很容易知道接收者的信箱了.怎么办呢?冰河原来是采用把信息写进自己里面.但是自己怎么写进自己里面呢?我们分析一下就知道答案了.
首先,第一步先修改注册表:在HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Policies/WinoldApp下新建一个双字节类型的键名为Disabled键值为1的新键,其作用是禁止运行DOS程序(包括批处理文件).当然你也可以用超级兔子之类的程序来修改.第二步:配置服务端种子,我们选择安装在<TEMP>目录下(原因:文件比<windows>、<system>下都要少),把<TEMP>目录下尽量清空,以便于我们下一步分析。
第三步:运行服务端,用客户端成功连接后远程修改配置,系统会弹出一个窗口:本次操作受限制.第四步:打开<TEMP>目录,发现除了服务端文件外,多了两个文件:NewFile.exe和sysclr.bat。击右键查看属性可以看出NewFile.exe跟服务端文件大小一样,从而知道它是服务端的备份。打开sysclr.bat,内容如下:
@echo off
:loop
del c:/windows/TEMP/NewFile.exe
if exist c:/windows/TEMP/NewFile.exe goto loop
del %0
得出结论了吧:)原来它采用的方法是先把自己拷贝为一个备份,然后对备份文件进行配置,最后用备份覆盖自己.我曾经就此写过一个演示程序http://www.138soft.com/htm/selfmodif.exe.那么说这个跟本文有什么关系呢?呵呵,我们用上面的方法来跟踪分析一下<<Windows优化大师>>的内存优化程序是怎么编写的.
运行<<Windows内存整理>>,然后设置释放628KB内存碎片.点&quot;整理&quot;,这时候打开进程管理器,发现系统启动了Wscript.exe程序.这个是Windows自身带的一个运行脚本的程序.当内存碎片整理完毕后,这个程序也随之退出了.我们再打开<TEMP>目录,重复上面步骤,发现整理内存的时候出现了一个memory.vbs文件.当内存碎片整理完毕后这个文件也消失了.我们用记事本打开它,内容如下:Mystring = Space(628000).把它拷贝到桌面然后运行它,效果跟运行<<Windows内存整理>>是一样的.
通过上面分析我们完全可以写出一个一模一样的程序来了.现在就动手吧!
运行Delphi,新建一个工程,往窗口放上两个Label,一个TrackBar1,一个Timer和一个Button.全部代码如下:
unit Unit1;

interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls, ComCtrls, ExtCtrls;

type
TForm1 = class(Tform)
Button1: Tbutton;
TrackBar1: TTrackBar;
Label1: Tlabel;
Label2: Tlabel;
Timer1: Ttimer;
procedure Button1Click(Sender: Tobject);
procedure TrackBar1Change(Sender: Tobject);
procedure Timer1Timer(Sender: Tobject);
private
procedure GetMemoryInfo;
function GetTempDir: string;
function CreateVbsFile(FileName:String;iKB:integer):boolean;
function WinExecAndWait32(FileName: string;
Visibility: Integer): Boolean;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation
{$R *.DFM}
function TForm1.WinExecAndWait32(FileName: string;
Visibility: Integer): Boolean;
//运行一个程序并等待其关闭
var
WorkDir: string;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin

GetDir(0, WorkDir);
FillChar(StartupInfo, Sizeof(StartupInfo), #0);
StartupInfo.cb := Sizeof(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
if not CreateProcess(nil,
Pchar(FileName), { pointer to command line string }
nil, { pointer to process security attributes }
nil, { pointer to thread security attributes }
True, { handle inheritance flag }
CREATE_NEW_CONSOLE or { creation flags }
NORMAL_PRIORITY_CLASS,
nil, { pointer to new environment block }
Pchar(WorkDir), { pointer to current directory name, Pchar}
StartupInfo, { pointer to STARTUPINFO }
ProcessInfo) { pointer to PROCESS_INF }
then

Result := False {-1}
else

begin

Application.ProcessMessages;
WaitforSingleObject(ProcessInfo.hProcess, INFINITE);
CloseHandle(ProcessInfo.hProcess);
{ to prevent memory leaks }
CloseHandle(ProcessInfo.hThread);
Result := true;
end;

end;

function TForm1.GetTempDir: string;//取得临时目录的路径
var
Buffer: array[0..1023] of Char;
begin

SetString(Result, Buffer, GetTempPath(SizeOf(Buffer), Buffer));
end;

function TForm1.CreateVbsFile(FileName:String;iKB:integer):boolean;//创建一个VBS文件
var
MyList:TStringList;
begin

Result:=False;
if FileExists(FileName) then
DeleteFile(FileName);
MyList:=TStringList.Create;
try
MyList.Clear;
MyList.Add('Mystring = Space('+IntToStr(iKB)+'000)');
MyList.SaveToFile(FileName);
finally
MyList.Free;
end;

Result:=True;
end;

procedure TForm1.GetMemoryInfo;//获取内存信息
var
MemStatus: TMEMORYSTATUS;
//定义内存结构变量
All,CanUse:integer;
begin

MemStatus.dwLength :=sizeof(TMEMORYSTATUS);
GlobalMemoryStatus(MemStatus);
//返回内存使用信息
All:=MemStatus.dwTotalPhys div 1024;
CanUse:=MemStatus.dwAvailPhys div 1024;
Label1.Caption :='共有内存:'+IntToStr(All)+'KB 可用内存:'+IntToStr(CanUse)+'KB';
//将内存信息显示出来
TrackBar1.Min:=1;
TrackBar1.Max:=All;
//最大值赋给TrackBar1
end;

procedure TForm1.Button1Click(Sender: Tobject);
var
StrFileName,StrCommand:String;
begin

StrFileName:=GetTempDir+'memory.vbs';
StrCommand:='Wscript.exe '+StrFileName;
if CreateVbsFile(StrFileName,TrackBar1.Position) then

if WinExecAndWait32(StrCommand,SW_HIDE) then

Application.MessageBox('整理内存碎片完毕!','Windows内存整理',MB_ICONINFORMATION+MB_OK)
else
Application.MessageBox('创建线程失败!','Windows内存整理',MB_ICONERROR+MB_OK)
else
Application.MessageBox('创建文件失败!','Windows内存整理',MB_ICONERROR+MB_OK);
if FileExists(StrFileName) then
DeleteFile(StrFileName);
end;

procedure TForm1.TrackBar1Change(Sender: Tobject);
begin

Label2.Caption:='整理时释放'+IntToStr(TrackBar1.Position)+'KB的内存碎片';
end;

procedure TForm1.Timer1Timer(Sender: Tobject);
begin

GetMemoryInfo;//定时刷新
end;

end.

-----------------------------------------------------------------------------------------------------
★作者:
陈经韬
 

Similar threads

后退
顶部