線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:13740
推到 Plurk!
推到 Facebook!

實體記憶體變少了

答題得分者是:anpino
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-06-25 15:00:43 IP:220.139.xxx.xxx 未訂閱
雖然我寫過 ■【BCB】【發表】StatPlus StandAlone Version (0.0.9.525)  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=25676 也知道如何取得每一個程式占用的記憶體,所得的結果與工作管理員上所記錄的是相同的。最近正對程式作長時間測試,在程式中會去記錄自己程式的記憶體使用量,而此數值與工作管理員相同,不過,也許是我的程式占有記憶體本來就比較大的緣故,發現實體記憶體的剩餘量似乎與「總實體記憶體 ─ 所有程式占用的實體記憶體」是不相等的?! 也許在您的電腦也是一樣,您可以由工作管理員算一算,目前所有程式占用的實體記憶體,以總實體記憶體減去它的值似乎比實體記憶體的剩餘量要大很多。 以我的實例,由工作管理員中計算所有應用程式占用實體記憶體約 250MB,而真實記憶體為 512MB 但顯示的可用實體記憶體卻只有 80MB 左右?! 為什麼會這樣?    在之前 China Join [BCB] [發表] 減少程式常駐時記憶體耗用的方法 http://delphi.ktop.com.tw/topic.php?topic_id=32333 有提到把程式最小化,可以省下實體記憶體。 我的程式占用約 160MB 的實體記憶體,最小化後,占用約 40MB,再最大化,也不會由 40 立刻變到 160,只是由 40MB 慢慢變大 還是 40幾MB,但是,由工作管理員中的「效能」頁面,所看到的可用實體記憶體,卻沒有因此而多出 100MB。    各位,如果沒有比較大的程式可以測試,可以利用本站的 ■【發表】KTOP 討論區離線閱讀程式(站長推薦) http://delphi.ktop.com.tw/topic.php?TOPIC_ID=47972    我實測是(由工作管理員看到的資料):執行前,可用實體記憶體 270MB 執行後,作個 進階→內容 test 的查詢動作,可用實體記憶體變成 75MB,而程式占用的記憶體卻只有 36MB    請問記憶體到那去了呢? 要得回來嗎?    http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc. 發表人 - dllee 於 2004/06/25 15:43:09
------
http://www.ViewMove.com
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-06-30 01:19:13 IP:61.64.xxx.xxx 未訂閱
http://www.maple5250.com/Windows Terminal Server.htm 上面那個是 亂 po的 哈哈 http://www.expresscomputeronline.com/20030915/techspace01.shtml 相同問題討論 記的還有篇 http://delphi.ktop.com.tw/topic.php?topic_id=45714 http://delphi.ktop.com.tw/topic.php?topic_id=45378 這一篇 http://delphi.ktop.com.tw/topic.php?topic_id=48266 http://delphi.ktop.com.tw/topic.php?topic_id=48959 http://delphi.ktop.com.tw/topic.php?topic_id=49888 http://delphi.ktop.com.tw/topic.php?topic_id=47449 http://delphi.ktop.com.tw/topic.php?topic_id=47675 http://delphi.ktop.com.tw/topic.php?topic_id=45714 http://www.sysinternals.com/ntw2k/freeware/procexp.shtml http://www.delphicorner.f9.co.uk/articles/forms1.htm http://www.sharewareriver.com/product.php?id=201 http://delphi.ktop.com.tw/topic.php?topic_id=44644 http://17slon.com/gp/gpprofile/ http://support.microsoft.com/default.aspx?scid=kb;EN-US;237361 http://forums.spywareinfo.com/index.php?showtopic=6609 暫時無蠅 蘇以等等 發表人 - conundrum 於 2004/06/30 13:12:50
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-06-30 12:12:52 IP:220.139.xxx.xxx 未訂閱
感謝 conundrum 的回應... 但... 希望有其他的方向或提示...    http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc.
------
http://www.ViewMove.com
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-06-30 12:26:09 IP:61.221.xxx.xxx 未訂閱
dllee 兄 還真的是 凹神一族的 困苦阿
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-06-30 14:20:28 IP:147.8.xxx.xxx 未訂閱
Hi dllee, did you count the 'System Cache'?
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-06-30 20:55:13 IP:211.76.xxx.xxx 未訂閱
引言: Hi dllee, did you count the 'System Cache'?
我直接把我的測試圖秀出: 在載入 KTOP Reader 之前的狀況: 在載入 KTOP Reader 之後並作進階搜尋以文章內容找 test 字串全部都找到後的狀況: 以一開始: 可用: 275620 系統快取:216604 後來狀況: 可用: 72092 系統快取:293036 KTOPReader: 33416 不論如何加,也是差很多。 http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc.
------
http://www.ViewMove.com
lovejingtao
一般會員


發表:10
回覆:33
積分:13
註冊:2003-04-16

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-07-01 13:54:48 IP:220.173.xxx.xxx 未訂閱
建议检查程序是否存在内存泄露. eg: program Project1; uses CheckMem,//Add it to the first line of project uses Forms, ...... 运行程序,退出后在程序目录下有一记录文件记录你的程序是否存在内存泄露. ================================================== unit CheckMem; file://Add it to the first line of project uses interface procedure SnapCurrMemStatToFile(Filename: string); implementation uses Windows, SysUtils, TypInfo; const MaxCount = High(Word); var OldMemMgr: TMemoryManager; ObjList: array[0..MaxCount] of Pointer; FreeInList: Integer = 0; GetMemCount: Integer = 0; FreeMemCount: Integer = 0; ReallocMemCount: Integer = 0; procedure AddToList(P: Pointer); begin if FreeInList > High(ObjList) then begin MessageBox(0, '内存管理监视器指针列表溢出,请增大列表项数!', '内存管理监视器', mb_ok); Exit; end; ObjList[FreeInList] := P; Inc(FreeInList); end; procedure RemoveFromList(P: Pointer); var I: Integer; begin for I := 0 to FreeInList - 1 do if ObjList[I] = P then begin Dec(FreeInList); Move(ObjList[I 1], ObjList[I], (FreeInList - I) * SizeOf(Pointer)); Exit; end; end; procedure SnapCurrMemStatToFile(Filename: string); const FIELD_WIDTH = 20; var OutFile: TextFile; I, CurrFree, BlockSize: Integer; HeapStatus: THeapStatus; Item: TObject; ptd: PTypeData; ppi: PPropInfo; procedure Output(Text: string; Value: integer); begin Writeln(OutFile, Text: FIELD_WIDTH, Value div 1024, ' KB(', Value, ' Byte)'); end; begin AssignFile(OutFile, Filename); try if FileExists(Filename) then begin Append(OutFile); Writeln(OutFile); end else Rewrite(OutFile); CurrFree := FreeInList; HeapStatus := GetHeapStatus; { 局部堆状态 } with HeapStatus do begin Writeln(OutFile, '===== ', ExtractFileName(ParamStr(0)), ',', DateTimeToStr(Now), ' ====='); Writeln(OutFile); Output('可用地址空间 : ', TotalAddrSpace); Output('未提交部分 : ', TotalUncommitted); Output('已提交部分 : ', TotalCommitted); Output('空闲部分 : ', TotalFree); Output('已分配部分 : ', TotalAllocated); Output('全部小空闲内存块 : ', FreeSmall); Output('全部大空闲内存块 : ', FreeBig); Output('其它未用内存块 : ', Unused); Output('内存管理器消耗 : ', Overhead); Writeln(OutFile, '地址空间载入 : ': FIELD_WIDTH, TotalAllocated div (TotalAddrSpace div 100), '%'); end; Writeln(OutFile); Writeln(OutFile, Format('当前出现 %d 处内存漏洞 :', [GetMemCount - FreeMemCount])); for I := 0 to CurrFree - 1 do begin Write(OutFile, I: 4, ') ', IntToHex(Cardinal(ObjList[I]), 16), ' - '); BlockSize := PDWORD(DWORD(ObjList[I]) - 4)^; Write(OutFile, BlockSize: 4, '($' IntToHex(BlockSize, 4) ')字节', ' - '); try Item := TObject(ObjList[I]); if PTypeInfo(Item.ClassInfo).Kind <> tkClass then { type info technique } write(OutFile, '不是对象') else begin ptd := GetTypeData(PTypeInfo(Item.ClassInfo)); ppi := GetPropInfo(PTypeInfo(Item.ClassInfo), 'Name'); { 如果是TComponent } if ppi <> nil then begin write(OutFile, GetStrProp(Item, ppi)); write(OutFile, ' : '); end else write(OutFile, '(未命名): '); Write(OutFile, Item.ClassName, ' (', ptd.ClassType.InstanceSize, ' 字节) - In ', ptd.UnitName, '.pas'); end except on Exception do write(OutFile, '不是对象'); end; writeln(OutFile); end; finally CloseFile(OutFile); end; end; function NewGetMem(Size: Integer): Pointer; begin Inc(GetMemCount); Result := OldMemMgr.GetMem(Size); AddToList(Result); end; function NewFreeMem(P: Pointer): Integer; begin Inc(FreeMemCount); Result := OldMemMgr.FreeMem(P); RemoveFromList(P); end; function NewReallocMem(P: Pointer; Size: Integer): Pointer; begin Inc(ReallocMemCount); Result := OldMemMgr.ReallocMem(P, Size); RemoveFromList(P); AddToList(Result); end; const NewMemMgr: TMemoryManager = ( GetMem: NewGetMem; FreeMem: NewFreeMem; ReallocMem: NewReallocMem); initialization GetMemoryManager(OldMemMgr); SetMemoryManager(NewMemMgr); finalization SetMemoryManager(OldMemMgr); if (GetMemCount - FreeMemCount) <> 0 then SnapCurrMemStatToFile(ExtractFileDir(ParamStr(0)) '\CheckMemory.Log'); end. 冷静的思考问题 充满激情的工作
lovejingtao
一般會員


發表:10
回覆:33
積分:13
註冊:2003-04-16

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-07-01 13:57:27 IP:220.173.xxx.xxx 未訂閱
建议检查程序是否存在内存泄露. eg: program Project1; uses CheckMem,//Add it to the first line of project uses Forms, ...... 运行程序,退出后在程序目录下有一记录文件记录你的程序是否存在内存泄露. ================================================== unit CheckMem; file://Add it to the first line of project uses interface procedure SnapCurrMemStatToFile(Filename: string); implementation uses Windows, SysUtils, TypInfo; const MaxCount = High(Word); var OldMemMgr: TMemoryManager; ObjList: array[0..MaxCount] of Pointer; FreeInList: Integer = 0; GetMemCount: Integer = 0; FreeMemCount: Integer = 0; ReallocMemCount: Integer = 0; procedure AddToList(P: Pointer); begin if FreeInList > High(ObjList) then begin MessageBox(0, '内存管理监视器指针列表溢出,请增大列表项数!', '内存管理监视器', mb_ok); Exit; end; ObjList[FreeInList] := P; Inc(FreeInList); end; procedure RemoveFromList(P: Pointer); var I: Integer; begin for I := 0 to FreeInList - 1 do if ObjList[I] = P then begin Dec(FreeInList); Move(ObjList[I 1], ObjList[I], (FreeInList - I) * SizeOf(Pointer)); Exit; end; end; procedure SnapCurrMemStatToFile(Filename: string); const FIELD_WIDTH = 20; var OutFile: TextFile; I, CurrFree, BlockSize: Integer; HeapStatus: THeapStatus; Item: TObject; ptd: PTypeData; ppi: PPropInfo; procedure Output(Text: string; Value: integer); begin Writeln(OutFile, Text: FIELD_WIDTH, Value div 1024, ' KB(', Value, ' Byte)'); end; begin AssignFile(OutFile, Filename); try if FileExists(Filename) then begin Append(OutFile); Writeln(OutFile); end else Rewrite(OutFile); CurrFree := FreeInList; HeapStatus := GetHeapStatus; { 局部堆状态 } with HeapStatus do begin Writeln(OutFile, '===== ', ExtractFileName(ParamStr(0)), ',', DateTimeToStr(Now), ' ====='); Writeln(OutFile); Output('可用地址空间 : ', TotalAddrSpace); Output('未提交部分 : ', TotalUncommitted); Output('已提交部分 : ', TotalCommitted); Output('空闲部分 : ', TotalFree); Output('已分配部分 : ', TotalAllocated); Output('全部小空闲内存块 : ', FreeSmall); Output('全部大空闲内存块 : ', FreeBig); Output('其它未用内存块 : ', Unused); Output('内存管理器消耗 : ', Overhead); Writeln(OutFile, '地址空间载入 : ': FIELD_WIDTH, TotalAllocated div (TotalAddrSpace div 100), '%'); end; Writeln(OutFile); Writeln(OutFile, Format('当前出现 %d 处内存漏洞 :', [GetMemCount - FreeMemCount])); for I := 0 to CurrFree - 1 do begin Write(OutFile, I: 4, ') ', IntToHex(Cardinal(ObjList[I]), 16), ' - '); BlockSize := PDWORD(DWORD(ObjList[I]) - 4)^; Write(OutFile, BlockSize: 4, '($' IntToHex(BlockSize, 4) ')字节', ' - '); try Item := TObject(ObjList[I]); if PTypeInfo(Item.ClassInfo).Kind <> tkClass then { type info technique } write(OutFile, '不是对象') else begin ptd := GetTypeData(PTypeInfo(Item.ClassInfo)); ppi := GetPropInfo(PTypeInfo(Item.ClassInfo), 'Name'); { 如果是TComponent } if ppi <> nil then begin write(OutFile, GetStrProp(Item, ppi)); write(OutFile, ' : '); end else write(OutFile, '(未命名): '); Write(OutFile, Item.ClassName, ' (', ptd.ClassType.InstanceSize, ' 字节) - In ', ptd.UnitName, '.pas'); end except on Exception do write(OutFile, '不是对象'); end; writeln(OutFile); end; finally CloseFile(OutFile); end; end; function NewGetMem(Size: Integer): Pointer; begin Inc(GetMemCount); Result := OldMemMgr.GetMem(Size); AddToList(Result); end; function NewFreeMem(P: Pointer): Integer; begin Inc(FreeMemCount); Result := OldMemMgr.FreeMem(P); RemoveFromList(P); end; function NewReallocMem(P: Pointer; Size: Integer): Pointer; begin Inc(ReallocMemCount); Result := OldMemMgr.ReallocMem(P, Size); RemoveFromList(P); AddToList(Result); end; const NewMemMgr: TMemoryManager = ( GetMem: NewGetMem; FreeMem: NewFreeMem; ReallocMem: NewReallocMem); initialization GetMemoryManager(OldMemMgr); SetMemoryManager(NewMemMgr); finalization SetMemoryManager(OldMemMgr); if (GetMemCount - FreeMemCount) <> 0 then SnapCurrMemStatToFile(ExtractFileDir(ParamStr(0)) '\CheckMemory.Log'); end. 冷静的思考问题 充满激情的工作
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-07-01 23:05:03 IP:211.76.xxx.xxx 未訂閱
感謝 lovejingtao 提供的方法。 您的方法可以用來判斷程式是否有 new 但不 delete 的狀況, 但我的問題是,工作管理員所記錄的可用實體記憶體到底是如何計算? 該值可以使用 GlobalMemoryStatus() 這個 API 取得。
引言:
The MEMORYSTATUS structure contains information about current memory availability. 
The GlobalMemoryStatus function uses this structure.     typedef struct _MEMORYSTATUS { // mst  
    DWORD dwLength;        // sizeof(MEMORYSTATUS) 
    DWORD dwMemoryLoad;    // percent of memory in use 
    DWORD dwTotalPhys;     // bytes of physical memory 
    DWORD dwAvailPhys;     // free physical memory bytes 
    DWORD dwTotalPageFile; // bytes of paging file 
    DWORD dwAvailPageFile; // free bytes of paging file 
    DWORD dwTotalVirtual;  // user bytes of address space 
    DWORD dwAvailVirtual;  // free user bytes 
} MEMORYSTATUS, *LPMEMORYSTATUS; 
用此函式所取得的 dwAvailPhys 與工作管理員上的值相同。 但是如同我秀的圖,可用記憶體似乎與程式占用的記憶體有一段差距。 為什麼有這個差距? 有可能可以減少這個差距嗎? http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc.
------
http://www.ViewMove.com
qoo1234
版主


發表:256
回覆:1167
積分:659
註冊:2003-02-24

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-07-02 01:05:04 IP:218.163.xxx.xxx 未訂閱
http://www.robursoft.de/mmonitor.html 含Visual C 原始碼與執行檔 http://www.robursoft.de/bin/memorymonitor.zip 發表人 - qoo1234 於 2004/07/02 01:47:59
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#11 引用回覆 回覆 發表時間:2004-07-02 22:43:26 IP:211.76.xxx.xxx 未訂閱
感謝 qoo1234 版主提供的資料 其原始碼如下: http://www.robursoft.de/bin/memorymonitor.html 基本上就是使用 GlobalMemoryStatus() 取得目前記憶體的資料。如同 ■【BCB】【發表】StatPlus StandAlone Version (0.0.9.525)  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=25676 一般。    lovejingtao 的方法很適合用來對自己的程式除錯。    to conundrum, 感謝您搜出那麼多相關的討論: 與最小化有關
引言: http://delphi.ktop.com.tw/topic.php?topic_id=45714 http://delphi.ktop.com.tw/topic.php?topic_id=45378 http://delphi.ktop.com.tw/topic.php?topic_id=47449 -> 好方法 http://www.expresscomputeronline.com/20030915/techspace01.shtml http://www.delphicorner.f9.co.uk/articles/forms1.htm
anpino 版主這篇實在是太精彩了(最近肚子不太舒服,看了這篇文章目前還無法消化 <>< face="Verdana, Arial, Helvetica">引言: http://delphi.ktop.com.tw/topic.php?topic_id=48266 記憶體管理:
引言: http://delphi.ktop.com.tw/topic.php?topic_id=48959 http://delphi.ktop.com.tw/topic.php?topic_id=49888 http://delphi.ktop.com.tw/topic.php?topic_id=47675 http://delphi.ktop.com.tw/topic.php?topic_id=44644
工具:
引言: http://www.sysinternals.com/ntw2k/freeware/procexp.shtml http://www.sharewareriver.com/product.php?id=201
基本上: 1. 程式最小化,可以省記憶體 2. 自己 Create 的要 FreeAndNil 3. 使用各式的記憶體查看工具,可以得到應用程式占用的記憶體大小及系統記憶體大小 這些都是已知的,而這並不是我的問題.... 我的問題是 【問題】實體記憶體變少了 主要是由工作管理員中所有程式占用實體記憶體加起來的總合與目前可用實體記憶體兩者相加與總實體記憶體不相符。william版主有提到要再算 'System Cache' 我想應該是 '系統快取記憶體'。 同樣,就算是「程式占用實體記憶體加起來的總合」+「目前可用實體記憶體」」+「系統快取記憶體」也還是不等於「已安裝的實體記憶體」? 只要是有 NT/2K/XP 系統,如果您有空的話,可以用計算機算一算。 特別是在執行 ■【發表】KTOP 討論區離線閱讀程式(站長推薦) http://delphi.ktop.com.tw/topic.php?TOPIC_ID=47972 之前,及執行 KTopForum.exe 後作進階內容搜尋,如此的比對是差異最多的。 也如同我的貼圖,這些實體記憶體到底是誰用去了? 是工作管理員應該是有漏記?! (在何種狀況下工作管理員會不記呢? 很好奇...) 是系統自己偷偷拿去用?! (在何種狀況下會發生?又如何能釋回呢?) 以 KTopForum.exe 為例,作一次進階內容搜尋幾乎要占去 200MB 的實體記憶體,而在工作管理員中卻只記錄占用實體記憶體 30MB,但由工作管理員的可用實體記憶體就可以發現少了 200MB,那沒記錄的 170MB 到那去了呢? 是否因為有使用資料庫(ADO,BDE)而資料庫在操作中所占用的記憶體都不算在使用資料庫的程式上嗎? 還是有其他的操作也不算在使用的應用程式頭上呢? 也許... 我應該要去問問比爾蓋茲... < href="http://www.ViewMove.com">http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc.
------
http://www.ViewMove.com
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#12 引用回覆 回覆 發表時間:2004-07-02 23:46:09 IP:61.64.xxx.xxx 未訂閱
http://www.jjhou.com/review1-16.htm 侯先生的書 應該還是有蹟可尋 除了 記憶體 虛擬記憶 幫助os處理 排程 還有殺咪 ExecPE() 函式 再A再A 第四章介紹 Memory-Mapped Files。這是一個非常重要的技術,是 NT 管理 App 和 DLL 的重要基石。基本想法是你可以在打開檔案後取得一個映射到檔案的指標,然後就可以把檔案內容當做在記憶體中一樣地運作,不必困擾應該先配置多少記憶體以及如何把內容分段讀進來分段處理等 "buffering" 瑣事。NT 本身利用這技術做三件事情 : http://www.tango04.com/products/vdw/download.php http://washitake.com/tips/old.php 藏鏡人 1.X 說的 http://support.microsoft.com/?kbid=837331 http://www.winnetmag.com/Windows/Articles/ArticleID/3864/pg/1/1.html http://www.winnetmag.com/Files/3864/Figure_04.gif 發表人 - conundrum 於 2004/07/03 00:30:35
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#13 引用回覆 回覆 發表時間:2004-07-03 10:04:54 IP:211.76.xxx.xxx 未訂閱
藏鏡人 1.X 說的 http://support.microsoft.com/?kbid=837331 http://www.winnetmag.com/Articles/Index.cfm?ArticleID=3864 真的不錯喔,可以讓我們更了解 Windows 內部的運作。 需要一些時間來消化...    lovejingtao 所提到的測試 new / delete 的次數,結果不如我的預期... 在 BCB5 Online Help 中
引言: GetMemoryManager, SetMemoryManager Example The following example implements a memory manager that counts the number of times the GetMem, FreeMem, and ReallocMem entry points are called. You must call the SetNewMemMgr routine to install the new memory manager. The new memory manager routines simply passes on the requests to the previous memory manager after incrementing the appropriate counter.
TMemoryManager* mmNew;
TMemoryManager* mmOld;
int iGetMemCount, iFreeMemCount, iReallocMemCount;    Pointer __fastcall NewGetMem(int iSize);
int __fastcall NewFreeMem(Pointer p);
Pointer __fastcall NewReallocMem(Pointer p, int iSize);    __fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
{
  mmNew = new TMemoryManager();
  mmOld = new TMemoryManager();      mmNew->GetMem = NewGetMem;      mmNew->FreeMem = NewFreeMem;
  mmNew->ReallocMem = NewReallocMem;      GetMemoryManager(*mmOld);      SetMemoryManager(*mmNew);
}    __fastcall TForm1::~TForm1()
{
  delete mmNew;
  delete mmOld;
}    Pointer __fastcall NewGetMem(int iSize)
{
  iGetMemCount  ;
  return mmOld->GetMem(iSize);
}    int __fastcall NewFreeMem(Pointer p)
{
  iFreeMemCount  ;
  return mmOld->FreeMem(p);
}    Pointer __fastcall NewReallocMem(Pointer p, int iSize)
{
  iReallocMemCount  ;
  return mmOld->ReallocMem(p, iSize);
}
實測的結果是 iGetMemCount, iFreeMemCount 這兩個數值,即使程式沒有作任動作,也是一直累加,應該是 VCL 內部運作時,也會一直 new/delete 或是作其他記憶體的安排,所以... 似乎無法拿來判斷是否真的程式內有 new 沒有 delete。 http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc. 發表人 - dllee 於 2004/07/03 13:52:29
------
http://www.ViewMove.com
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#14 引用回覆 回覆 發表時間:2004-07-03 14:05:10 IP:61.221.xxx.xxx 未訂閱
http://www.sciences.univ-nantes.fr/info/enseignement/deug/info1A/freepascal/ref/node17.html http://www.delphibbs.com/keylife/iblog_show.asp?xid=2688 http://www.cs.ut.ee/~jaanus/prog2/freepas/doc/prog/node10.html http://www.javaworld.com.tw/jute/post/view?bid=28&id=39522&sty=3&age=0    http://www.asus.it/support/chinese/techref/virtual/index.aspx http://www.memturbo.com/ http://www.slat.org/project/software-map/v1.01/node91.html http://www.csie.ntu.edu.tw/~wcchen/asm98/asm/proj/b85506061/chap2/paging.html http://home.so-net.com.hk/~lfchan/ebook/source/129.htm http://nthucad.cs.nthu.edu.tw/~yyliu/personal/nou/02os/qa16.txt http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dngenlib/html/msdn_manamemo.asp    anpino 版主的網站 實在 令人髮指 哈哈 http://home.educities.edu.tw/perfectsw/Second.htm 不得不po實在是 十分恐怖 不知 阿湯哥 布螺絲 ㄟ安轉 沒看到 粉  最欠扁的行為 < src="http://delphi.ktop.com.tw/download/upload\52614_123.jpg"> 哈哈 發表人 - conundrum 於 2004/07/03 19:16:11
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#15 引用回覆 回覆 發表時間:2004-07-03 18:29:30 IP:211.76.xxx.xxx 未訂閱
感謝大家提供的各式資訊,我想此題也許真的需要問 MS 的人員才知道...    我把大家的資料整理成一個測試程式 ■ Memory Status http://delphi.ktop.com.tw/topic.php?TOPIC_ID=52613
引言: Allocate Memory: new 一塊記憶體 -> 占用虛擬記憶體, TotalAddrSpace,TotalAllocated 增加 Allocate&Use: new 一塊記憶體並給值 -> 占用實體及虛擬記憶體, TotalAddrSpace,TotalAllocated 增加 Use Again: 對於指定的記憶體再給一次值 -> 如果之前沒有占用實體記憶體, 則按下後會占用實體記憶體 Clear Use Status:對於已給值的記憶體會打*號,此按鈕只是清除星號 Free Memory: delete 指定的記憶體 -> 占用的實體記憶體放釋放,但虛擬記憶體不一定會釋放, 可以看到 TotalAllocated 減少,但 TotalAddrSpace 不一定會減少,當 TotalAddrSpace 減少 時,占用的虛擬記憶體就會釋放。 Free ALL: 幫您按下每一個 Item 的 Free Memory,最後結果可能與最初狀態不同 Like Min...: 像是最小化再還原的狀況,把實體記憶體儘可能都釋放了。此時如果左邊列表還有東西, 可以按下 Use Again 可以看到程式又占用實體記憶體了。而此過程,占用虛擬記憶體的大小是不變的。
由此測試程式,可以知道系統如何處理「看得到的部分」的實體記憶體及虛擬記憶體。 如果您有興趣可以做一個實驗:(請同時開工作管理員查看 MemoryStatus.exe 的實體記憶體使用量 1. 執行此測試程式,記下此時可用的實體記憶體(AvailPhys) 2. 按 Allocate&Use 多次(每次占用1MB),至少 10 次,您可以發現 AvailPhys 也減少相同的大小 3. 按下 Like Min... , 您會發現實體記憶體占用變成只有 1MB 左右,但 AvailPhys 並沒有立刻回復。而此時系統其他的程式也沒有明顯的增加記憶體使用量,而這是造成我所提的問題的原因之一。 4. 請您都不要操作,等...等...等...,在等的過程,您會發現,AvailPhys一直變多,同樣,此時系統其他的程式也沒有明顯的減少記憶體。 5. 最後 AvailPhys 會回復到之前的水位,不過還是有一點差 以上的測試可以找出一種使 程式占用實體記憶體加起來的總合」+「目前可用實體記憶體」」+「系統快取記憶體」不等於「已安裝的實體記憶體」 的原因,不過我想應該還有其他原因,如 > < href="http://www.ViewMove.com">http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc.
------
http://www.ViewMove.com
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#16 引用回覆 回覆 發表時間:2004-07-05 15:21:27 IP:211.23.xxx.xxx 未訂閱
dllee版大... 看來您似乎只是不小心忘記了page 的... 記憶體分配方式而已啦~~ 下面這幾篇可以讓您恢復記憶喔!! 1.記憶體管理 http://www.slat.org/project/software-map/v1.01/node91.html 2. 分頁架構 http://www.csie.ntu.edu.tw/~wcchen/asm98/asm/proj/b85506061/chap2/paging.html 3.分頁保護 http://www.csie.ntu.edu.tw/~wcchen/asm98/asm/proj/b85506061/chap3/page.html 4.實體記憶體 Vs 虛擬記憶體 http://www.asus.com/support/chinese/techref/virtual/index.aspx 5.分頁法記憶體管理的執行方式 http://vrschool.ice.cycu.edu.tw/vrschool/Course/OS/投影片/作業系統第八章/sld032.htm ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D Anpinos Middle Earth http://anpino.hp.infoseek.co.jp/ -------------------------------
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#17 引用回覆 回覆 發表時間:2004-07-05 20:48:31 IP:211.76.xxx.xxx 未訂閱
感謝 anpino 版主提供的資料 < > 說真的,我從來都沒有輸入過這類的資料進我的大腦... 我想辨法填丫一下... < > 另外,不知道您有玩 ■ Memory Status http://delphi.ktop.com.tw/topic.php?TOPIC_ID=52613 在其中的 TotalAddrSpace TotalUncommitted TotalCommitted TotalAllocated 應該算是對虛擬記憶體的吧,至少 TotalAllocated 的大小會反應在此應用程式占用虛擬記憶體的大小(由工作管理員由查看)。 對於實體記憶體,我想應該有類似的東西,在按下 Like Min... 時,TotalAllocated 算是立刻變小了,而工作管理員所看到此程式實體記憶體的占用也變小了,但是,此時的 TotalUncommitted 也許還很大,所以可用的實體記憶體沒有立刻變大。 在 Windows 系統自我清除後,TotalUncommitted 變小,可用的實體記憶體也才變大。 以這樣的解釋,對於一般的狀況應該是可以解釋得過去,我也可以理解。 但是對於 KTopForum.exe ,作一次進階內容搜尋幾乎要占去 200MB 的實體記憶體,而在工作管理員中卻只記錄占用實體記憶體 30MB,但由工作管理員的可用實體記憶體就可以發現少了 200MB,那沒記錄的 170MB 到那去了呢? 以您所建議的資料中提到: http://www.asus.com/support/chinese/techref/virtual/index.aspx
引言: 基 本 上 有 關 記 憶 體 的 分 配 方 式, 可 分 為 "分 段" 及 "分 頁" 兩 種. 分 段 是 記 憶 體 配 置 的 一 種 方 式,它 依 照 程 式 所 需 的 記 憶 體 實 際 大 小,來 分 配 記 憶 體 位 址。 另 一 種 記 憶 體 配 置 方 式 是 分 頁 (Paging),分 頁 的 配 置 法 是 固 定 大 小。 例 如 某 一 個 應 用 程 式 需 要 10 KB 的 記 憶 體,利 用 分 段 記 憶 體 配 置 法,則 作 業 系 統 會 分 配 一 個 10 KB 大 小 的 記 憶 區 塊; 若 改 用 分 頁 記 憶 體 配 置 法,假 設 每 一 頁 大 小 為 4 KB,則 作 業 系 統 會 分 配 3 個 記 憶 頁 給 該 程 式,於 是 應 用 程 式 便 取 得 12 KB 的 記 憶 空 間。 一 般 在 實 際 記 憶 體 (Physical Memory) 中,作 業 系 統 均 採 取 分 段 的 配 置 法,如 此 可 避 免 配 置 不 完 整 的 空 間 浪 費。 在 虛 擬 記 憶 體 (Virtual Memory) 中,則 記 憶 體 配 置 法 才 區 分 為 分 段 配 置 和 分 頁 配 置。
http://vrschool.ice.cycu.edu.tw/vrschool/Course/OS/投影片/作業系統第八章/sld034.htm
引言: 分頁法的特性 ■ 絕對不會發生外部支離破碎問題。 ■ 會發生內部支離破碎,因為若頁框未被填滿程式或資料,則形成浪費。 ■ 平均有1/2頁的內部支離破碎。 ■ 頁大小大致上在2KB或4KB左右。
就算是以分頁法來處理實體記憶體,以 KTopForum.exe 測試的例子,除非故意先 new 一大堆近 2K 或 4K 大小的記憶體,再把它們都變小成幾百BYTES,才有可能工作管理員記錄的 KTopForum.exe 占用實體 30MB 但實際已占去 200MB。 這是我比較不能理解的... 視動科技 VMASK - ViewMove Automation Software Kernel
------
http://www.ViewMove.com
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#18 引用回覆 回覆 發表時間:2004-07-06 08:50:52 IP:211.23.xxx.xxx 未訂閱
提示一下:    工作管理員只是可以"看"memory page, 有一個地方可以設定並影響到memory page 喔! [我的電腦]->滑鼠右鍵->[內容]->[進階]->[效能選項] ->虛擬記憶體->[變更] 看看page的總計 & 分頁大小 ~~ ----------------------- 這樣講好像不清不楚... 那我用您的
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#19 引用回覆 回覆 發表時間:2004-07-06 09:59:14 IP:220.139.xxx.xxx 未訂閱
感謝受過正規訓練的 anpino 版主加入測試行列  ■ href="http://www.ViewMove.com" target="blank">視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/07/06 10:03:12
------
http://www.ViewMove.com
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#20 引用回覆 回覆 發表時間:2004-07-08 14:13:51 IP:211.23.xxx.xxx 未訂閱
感謝 dllee 版大貼心地修改程式, 不必再開工作管理員 即可方便測試。    最近工作比較趕, 所以這類需要較多時間的測試會回的晚一些。 這幾天研究一下, 再把結果po上來, 不好意思, 遲了許多時間, 還望dllee 版大海涵。    
引言: 感謝受過正規訓練的 anpino 版主加入測試行列 < face="Verdana, Arial, Helvetica"> < >...< >< >...正規訓練< > 在下沒有受過什麼訓練耶... @@" 也不知道所謂的"正規訓練"是啥玩意兒... (當機中...) ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D Anpinos Middle Earth http://anpino.hp.infoseek.co.jp/ -------------------------------
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#21 引用回覆 回覆 發表時間:2004-07-08 18:39:25 IP:211.76.xxx.xxx 未訂閱
哈哈,看了您的網站,相信 應用數學系畢業 (主修 資工 & 分析)(畢業名次(不分主修) : 11) 如果還不算受過正規訓練,那就是與生俱來的天才囉 像我這種非資工出身,又不看進階的書,只由實測去歸納的黑手,相信您應該可以給我更多 href="http://www.ViewMove.com" target="blank">視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/07/08 18:51:15
------
http://www.ViewMove.com
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#22 引用回覆 回覆 發表時間:2004-07-09 13:33:53 IP:211.23.xxx.xxx 未訂閱
引言: to william 大大, 除了 'System Cache' 外,還有什麼是您可能認為造成 「程式占用實體記憶體加起來的總合」+「目前可用實體記憶體」+「系統快取記憶體」不等於「已安裝的實體記憶體」? 能再多給些提示嗎?
http://blog.joycode.com/qqchen/posts/16434.aspx 這個應該有幫助。 ps. 我...我知道"正規訓練"是什麼意思了...(汗) (字也不用放那~~麼大咩...) 其實我主攻數學啦! ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D Anpinos Middle Earth http://anpino.hp.infoseek.co.jp/ -------------------------------
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#23 引用回覆 回覆 發表時間:2004-07-09 20:07:28 IP:211.76.xxx.xxx 未訂閱
這個資料真的不錯 http://blog.joycode.com/qqchen/posts/16434.aspx 感謝分享 < > 以這篇所說的,工作管理員的程式實體記憶體使用量只能當參考 < > 也就是說,這個問題應該 K K 比爾蓋茲,請他出一個工作管理員的 patch < href="http://www.ViewMove.com" target="blank">視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/07/09 20:37:37
------
http://www.ViewMove.com
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#24 引用回覆 回覆 發表時間:2004-07-10 00:33:12 IP:61.64.xxx.xxx 未訂閱
http://www.yourwaresolutions.com/ FreeRAM XP Lite FreeRAM XP Lite has been replaced by FreeRAM XP Pro. FreeRAM XP Pro offers the same functionality as FreeRAM XP Lite, but with many more options and much more customizability. Both programs are free of cost. It is highly recommended that you download and use FreeRAM XP Pro instead of FreeRAM XP Lite. However, we retain FreeRAM XP Lite 1.03 in English and in Spanish here for completeness and as a courtesy to users who would like to keep using FreeRAM XP Lite. Click here to download FreeRAM XP Lite 1.03 in English Click here to download FreeRAM XP Lite 1.03 in Spanish 不錯玩 哈哈
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#25 引用回覆 回覆 發表時間:2004-07-10 17:00:50 IP:203.204.xxx.xxx 未訂閱
如果真要的用 Free Memory 的軟體,那就用 ■【BCB】【發表】StatPlus StandAlone Version (0.0.9.525)  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=25676 良心的建議是...不要使用 Free Memory 或 Memory Free 的軟體,因為,使用後,也許實體記憶體是空出來了,但是系統反而變慢,所以,最好是不要使用,除非真的必要。 相關討論: ■[心得] 要求系統釋放記憶體 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=19907 視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/07/10 17:03:18
------
http://www.ViewMove.com
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#26 引用回覆 回覆 發表時間:2004-07-13 10:32:18 IP:211.23.xxx.xxx 未訂閱
終於能抽出一些空閒時間看看這個題目了。    仔細k完dllee版大的"題目"&"描述"之後, 才發現,根本不用測,因為用Task Manager一定測不出來。 (除非用hacker手段把win底層挖出來瞧。)    以下是敝人對memory部分所知道的概念, 是從撰寫程式的觀察中得來, 不一定是完全正確, 參考即可。    1) 首先,向系統new一塊memory,它只是改變flag, (詳見侯捷的相關書籍) 直到會使用到這塊memory時(例如使用class的某個成員)才會真的配置一塊。 2) 加上視窗在"可能閒置"時(如切換視窗、開新視窗、最小化...), window就會執行memory page的動作, 但是window只是將"部分"memory做page, 所以我們無法從Task Manager得知到底做了多少page。 3) 即便做了page,window也不見得會將被page的data丟到Committed Virtual Memory,它可能還在Physical Memory 中,直到閒置逾時才會丟過去。    1 & 3 就是所謂的"怠惰配頁機制"。    結論:這是Windows Memory Management的問題。    ps. pagefile在98/me中是Win386.swp;在200/xp中是Pagefile.sys。 一般情況下,Virtual Memory在H.D中占的空間約是Physical Memory 的1.5倍左右。    其他的↓都有了 http://umeet.uninet.edu/conferencias/RikVanRiel/mmtour.html(←大綱) http://blog.joycode.com/qqchen/posts/16434.aspx    引用More on Memory Usage 如下:  
引言: Q: Is .NET Alone? A: Nope! 前面Saucer说过了,这不是.NET的问题,所有Windows程序都有类似的行为。例如下面的C程序: void main { while(1); } //死循环,便于我们察看Task Manager 初次运行在我的机器上Mem Usage是632K,把Console最小化以后再恢复,Mem Usage变成了36K。显然,这不是一个.NET独有的问题,而是Windows Memory Management的问题。那么和.NET的GC机制也不会有太大的关系——虽然问题的表现形式很容易让人联想到GC。 Q: How much memory does my program use? A: 回答这个问题并不容易。先来看看操作系统虚拟内存管理的一些基本概念:每个Windows进程都拥有4G的地址空间,但是你的机器显然没有4G的物理内存。在多任务环境下,所有进程使用的内存总和可以超过计算机的物理内存。在特定的情况下,进程的一部分可能会从物理内存中删除而被暂存在硬盘的文件里(pagefile),当进程试图访问这些被交换到pagefile里的内存的时候,系统会产生一个缺页中断(page fault),这时候Windows内存管理器会负责把对应的内存页重新从硬盘调入物理内存。 在某个时间内,一个进程可以直接访问到的物理内存(不发生缺页中断)叫做这个进程的Working Set;而一个进程从4G的地址空间当中实际分配(commit)了的、可访问的内存称为Committed Virtual Memory。Committed VM可能存在于Page File当中,WorkingSet则一定位于物理内存。 所以要回答上面的问题先要反问一句:What're you talking about? Physical Memory or Committed Memory? Q: What is this "Mem Usage" data? A: From Task Manager Help: In Task Manager, the current Working Set of a process, in kilobytes. Mem Usage这个名字多少有些误导。它只表示这个进程当前占用的物理内存,也就是WorkingSet。WorkingSet不表示进程当前“占用”的所有虚拟内存,该进程可能还有一部分数据被交换到pagefile当中。这些数据只有在被访问的时候才会被加载到物理内存。 Task Manager有另一列数据:VM Size,表示了一个进程分配的虚存(Committed Visual Memory)——实际的定义要比这个复杂一些,但这个定义对我们目前分析的问题已经足够了。以前面的C程序为例,在最小化前后的VM Size都是176K,并没有变化。 所以,结论很简单:当一个Windows程序被最小化的时候,Windows内存管理器把该进程的WorkingSet减到最小(根据先进先出FIFO或者最近最少使用LRU),把大部分数据交换到pagefile里。这很容易理解:我们通常总是希望为前台的应用程序留出更多物理内存,从而具有更好的性能。当该程序从最小化恢复的时候,Windows也不会完全加载程序的所有虚存,只是加载了必要的部分。这也很容易理解:程序启动阶段的代码通常在启动之后很少访问(对.NET程序尤其如此,向fusion这样的模块在程序正常加载之后如果没有用到Reflection通常用不到)。 Q: So, Do we want a smaller workingset, or a larger one? A: It depends. Conventional Wisdom tells us: The smaller, the better. 但是在虚存的问题上却没这么简单。如果WorkingSet太小,程序运行过程中会产生很多缺页中断,这会严重影响程序的性能。另一方面,WorkingSet太大会浪费“宝贵的”物理内存,降低整个系统的性能。 通常情况下(除非是对性能非常敏感的应用程序,并且你对Windows的内存管理了如指掌),建议不要在程序中自己调整WorkingSet的大小,而把这个任务交给Windows内存管理器。调整的方法Saucer有提到: SetProcessWorkingSetSize(); Q: Final Question, Does my program really occupy that much physical memory? A: 这个问题看上去土了点——那个数字明明白白的写在Task Manager里面。 sam1111用vadump检查的结果显示进程WorkingSet减小的主要原因是很多DLL在从最小化恢复的时候没有被加载到物理内存。我们知道DLL的一个特点是代码共享,以NTDLL.DLL为例,整个Windows系统的几乎所有应用程序(具体地说,Win32子系统的所有程序)都需要引用NTDLL.DLL,如果每人一份,光这个文件就的占用几十兆内存。Windows地解决办法是只在物理内存中保存一份NTDLL.DLL的COPY,所有引用这个DLL的程序都把这一份COPY映射到自己的内存空间里面,共享NTDLL.DLL的代码段(每个进程的数据段仍然是独立的)。所以虽然NTDLL.DLL的大小被计算在你的程序的WorkingSet里面,但是从你的程序中去掉对这个DLL的引用并不会真的释放多少物理内存——你不用,别人还在用呢! 所以,你的程序“独占”的物理内存远没有Mem Usage所表示的那么多,需要从Mem Usage里面扣除很多Shared Code Page (vadump里面可以看到)。 结论?不要参考Task Manager的Mem Usage数据,那个数据的大小对程序性能没有直接影响。 用Perfomence Monitor里面与.NET相关的Counter要容易、准确的多。
嗯... 果然還是沒有解決dllee版大的疑惑。 ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#27 引用回覆 回覆 發表時間:2004-07-14 20:44:47 IP:211.76.xxx.xxx 未訂閱
最後似乎問題只在於, 我拿了一把官方的尺,去量長度, 但是那個官方的尺沒有人驗證過, 連官方自己都沒有保證它量得準!!    感謝大家參與討論,謝謝。 特別感謝 anpino 版主告訴我,這把官方的尺是不準的, 在此之前,我一直以為它是準的  < href="http://www.ViewMove.com" target="blank">視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/07/14 20:46:55
------
http://www.ViewMove.com
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#28 引用回覆 回覆 發表時間:2004-07-15 13:03:18 IP:211.23.xxx.xxx 未訂閱
dllee版大謙虛了, 這只不過是敝人對memory部分所知道的概念, 是從撰寫程式的觀察中得來, 不一定是完全正確, 參考即可。    
引言: 特別感謝 anpino 版主告訴我,這把官方的尺是不準的, 在此之前,我一直以為它是準的 < face="Verdana, Arial, Helvetica"> 應該說, 這把官方的尺"很可能"是不準的。 ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D Anpinos Middle Earth http://anpino.hp.infoseek.co.jp/ -------------------------------
系統時間:2024-11-22 11:40:02
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!