當前位置:首頁 » 以太坊知識 » 以太坊blockheader

以太坊blockheader

發布時間: 2021-08-17 08:14:35

① c++ 獲取文件版本信息

c++ 獲取文件版本信息
文件信息結構描述:

struct VS_FIXEDFILEINFO {

DWORD dwSignature; //=0xFEEFO4BD
DWORD dwStrucVersion; //該結構的版本信息,分高低版本
DWORD dwFileVersionMS; //主文件版本
DWORD dwFileVersionLS; //次文件版本
DWORD dwProctVersionMS; //主產品版本
DWORD dwProctVersionLS; //次產品版本
DWORD dwFileFlagsMask; //文件標志掩碼
DWORD dwFileFlags; //文件標志(是否包含調試版本,動態版本結構...)
DWORD dwFileOS; //文件原定的操作系統(VOS_DOS,VOS_NT,VOS__WINDOWS16...)
DWORD dwFileType; //文件類型(VFT_UNKNOWN,VFT_APP,VFT_DLL...)
DWORD dwFileSubtype; //當dwFileType為VFT_APP或VFT_DLL時該值為0,當為驅動信息VFT_APP或字體信息時該值包含其具體的信息
DWORD dwFileDateMS; //主時間戳
DWORD dwFileDateLS; //次時間戳
};

===============================================
struct st_Language
{
WORD wLanguageID;
WORD wCodePage;
};

CString str("D:\\test\\test.exe");
DWORD dwSize = GetFileVersionInfoSize(str,NULL);
if(0 == dwSize) return;
LPBYTE pBlock = (BYTE*)malloc(dwSize);
bool b = GetFileVersionInfo(str,0,dwSize,pBlock);
char* pVerValue = NULL;
UINT nlen1 = 0;
VerQueryValue(pBlock,TEXT("file://VarFileInfo//Translation"),
(LPVOID*)&pVerValue,&nlen1);

//獲取語言
char* pLanValue = NULL;
UINT nLen2 = 0;
VerQueryValue(pBlock,"VarFileInfo\\Translation",(LPVOID*)&pLanValue,&nLen2);
//080404b0為中文
st_Language stlang = *((st_Language *)pLanValue);
//獲取版本屬性
VerQueryValue(pBlock,TEXT("file://%22),(LPVOID*)%26pVerValue,%26nlen1/);
VS_FIXEDFILEINFO *pfixfileinfo = (VS_FIXEDFILEINFO *)pVerValue;
//修改屬性
pfixfileinfo->dwFileVersionLS = 1234;
pfixfileinfo->dwFileVersionMS = 4321;
pfixfileinfo->dwProctVersionLS = 101;
pfixfileinfo->dwProctVersionMS = 1010;
//修改資源
HANDLE handle = BeginUpdateResource(str,FALSE);
BOOL result = UpdateResource(handle
,RT_VERSION
,MAKEINTRESOURCE(1)
,stlang.wLanguageID
,pBlock
,dwSize);
if (result == FALSE)
{
AfxMessageBox("Updata Resource False.");
}
EndUpdateResource(handle,FALSE);

free(pBlock);

② java execl 導入數據時位元組錯誤 如何解決

這個好像是poi的一個bug,你可以到官網上下個最新的包試試,或用jxl

③ Visual Leak Detector 內存泄露檢測,該怎麼處理

下面讓我們來介紹如何使用這個小巧的工具。
首先從網站上下載zip包,解壓之後得到vld.h, vldapi.h, vld.lib, vldmt.lib, vldmtdll.lib, dbghelp.dll等文件。將.h文件拷貝到Visual C++的默認include目錄下,將.lib文件拷貝到Visual C++的默認lib目錄下,便安裝完成了。因為版本問題,如果使用windows 2000或者以前的版本,需要將dbghelp.dll拷貝到你的程序的運行目錄下,或其他可以引用到的目錄。
接下來需要將其加入到自己的代碼中。方法很簡單,只要在包含入口函數的.cpp文件中包含vld.h就可以。如果這個cpp文件包含了stdafx.h,則將包含vld.h的語句放在stdafx.h的包含語句之後,否則放在最前面。如下是一個示常式序:
#include <vld.h>
void main()
{

}
接下來讓我們來演示如何使用Visual Leak Detector檢測內存泄漏。下面是一個簡單的程序,用new分配了一個int大小的堆內存,並沒有釋放。其申請的內存地址用printf輸出到屏幕上。
#include <vld.h>
#include <stdlib.h>
#include <stdio.h>

void f()
{
int *p = new int(0x12345678);
printf("p=%08x, ", p);
}

void main()
{
f();
}
編譯運行後,在標准輸出窗口得到:
p=003a89c0

在Visual C++的Output窗口得到:

WARNING: Visual Leak Detector detected memory leaks!
---------- Block 57 at 0x003A89C0: 4 bytes ------------57號塊0x003A89C0地址泄漏了4個位元組
Call Stack: --下面是調用堆棧
d:\test\testvldconsole\testvldconsole\main.cpp (7): f--表示在main.cpp第7行的f()函數
d:\test\testvldconsole\testvldconsole\main.cpp (14): main –雙擊以引導至對應代碼處
f:\rtm\vctools\crt_bld\self_x86\crt\src\crtexe.c (586): __tmainCRTStartup
f:\rtm\vctools\crt_bld\self_x86\crt\src\crtexe.c (403): mainCRTStartup
0x7C816D4F (File and line number not available): RegisterWaitForInputIdle
Data: --這是泄漏內存的內容,0x12345678
78 56 34 12 xV4..... ........

Visual Leak Detector detected 1 memory leak.
第二行表示57號塊有4位元組的內存泄漏,地址為0x003A89C0,根據程序控制台的輸出,可以知道,該地址為指針p。程序的第7行,f()函數里,在該地址處分配了4位元組的堆內存空間,並賦值為0x12345678,這樣在報告中,我們看到了這4位元組同樣的內容。
可以看出,對於每一個內存泄漏,這個報告列出了它的泄漏點、長度、分配該內存時的調用堆棧、和泄露內存的內容(分別以16進制和文本格式列出)。雙擊該堆棧報告的某一行,會自動在代碼編輯器中跳到其所指文件的對應行。這些信息對於我們查找內存泄露將有很大的幫助。
這是一個很方便易用的工具,安裝後每次使用時,僅僅需要將它頭文件包含進來重新build就可以。而且,該工具僅在build Debug版的時候會連接到你的程序中,如果build Release版,該工具不會對你的程序產生任何性能等方面影響。所以盡可以將其頭文件一直包含在你的源代碼中。
Visual Leak Detector工作原理
下面讓我們來看一下該工具的工作原理。
在這之前,我們先來看一下Visual C++內置的內存泄漏檢測工具是如何工作的。Visual C++內置的工具CRT Debug Heap工作原來很簡單。在使用Debug版的malloc分配內存時,malloc會在內存塊的頭中記錄分配該內存的文件名及行號。當程序退出時CRT會在main()函數返回之後做一些清理工作,這個時候來檢查調試堆內存,如果仍然有內存沒有被釋放,則一定是存在內存泄漏。從這些沒有被釋放的內存塊的頭中,就可以獲得文件名及行號。
這種靜態的方法可以檢測出內存泄漏及其泄漏點的文件名和行號,但是並不知道泄漏究竟是如何發生的,並不知道該內存分配語句是如何被執行到的。要想了解這些,就必須要對程序的內存分配過程進行動態跟蹤。Visual Leak Detector就是這樣做的。它在每次內存分配時將其上下文記錄下來,當程序退出時,對於檢測到的內存泄漏,查找其記錄下來的上下文信息,並將其轉換成報告輸出。

初始化
Visual Leak Detector要記錄每一次的內存分配,而它是如何監視內存分配的呢?Windows提供了分配鉤子(allocation hooks)來監視調試堆內存的分配。它是一個用戶定義的回調函數,在每次從調試堆分配內存之前被調用。在初始化時,Visual Leak Detector使用_CrtSetAllocHook注冊這個鉤子函數,這樣就可以監視從此之後所有的堆內存分配了。
如何保證在Visual Leak Detector初始化之前沒有堆內存分配呢?全局變數是在程序啟動時就初始化的,如果將Visual Leak Detector作為一個全局變數,就可以隨程序一起啟動。但是C/C++並沒有約定全局變數之間的初始化順序,如果其它全局變數的構造函數中有堆內存分配,則可能無法檢測到。Visual Leak Detector使用了C/C++提供的#pragma init_seg來在某種程度上減少其它全局變數在其之前初始化的概率。根據#pragma init_seg的定義,全局變數的初始化分三個階段:首先是compiler段,一般c語言的運行時庫在這個時候初始化;然後是lib段,一般用於第三方的類庫的初始化等;最後是user段,大部分的初始化都在這個階段進行。Visual Leak Detector將其初始化設置在compiler段,從而使得它在絕大多數全局變數和幾乎所有的用戶定義的全局變數之前初始化。

記錄內存分配
一個分配鉤子函數需要具有如下的形式:
int YourAllocHook( int allocType, void *userData, size_t size, int blockType, long requestNumber, const unsigned char *filename, int lineNumber);
就像前面說的,它在Visual Leak Detector初始化時被注冊,每次從調試堆分配內存之前被調用。這個函數需要處理的事情是記錄下此時的調用堆棧和此次堆內存分配的唯一標識——requestNumber。
得到當前的堆棧的二進製表示並不是一件很復雜的事情,但是因為不同體系結構、不同編譯器、不同的函數調用約定所產生的堆棧內容略有不同,要解釋堆棧並得到整個函數調用過程略顯復雜。不過windows提供一個StackWalk64函數,可以獲得堆棧的內容。StackWalk64的聲明如下:
BOOL StackWalk64(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME64 StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE64 GetMoleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
STACKFRAME64結構表示了堆棧中的一個frame。給出初始的STACKFRAME64,反復調用該函數,便可以得到內存分配點的調用堆棧了。
// Walk the stack.
while (count < _VLD_maxtraceframes) {
count++;
if (!pStackWalk64(architecture, m_process, m_thread, &frame, &context,
NULL, pSymFunctionTableAccess64, pSymGetMoleBase64, NULL)) {
// Couldn't trace back through any more frames.
break;
}
if (frame.AddrFrame.Offset == 0) {
// End of stack.
break;
}

// Push this frame's program counter onto the provided CallStack.
callstack->push_back((DWORD_PTR)frame.AddrPC.Offset);
}
那麼,如何得到初始的STACKFRAME64結構呢?在STACKFRAME64結構中,其他的信息都比較容易獲得,而當前的程序計數器(EIP)在x86體系結構中無法通過軟體的方法直接讀取。Visual Leak Detector使用了一種方法來獲得當前的程序計數器。首先,它調用一個函數,則這個函數的返回地址就是當前的程序計數器,而函數的返回地址可以很容易的從堆棧中拿到。下面是Visual Leak Detector獲得當前程序計數器的程序:
#if defined(_M_IX86) || defined(_M_X64)
#pragma auto_inline(off)
DWORD_PTR VisualLeakDetector::getprogramcounterx86x64 ()
{
DWORD_PTR programcounter;

__asm mov AXREG, [BPREG + SIZEOFPTR] // Get the return address out of the current stack frame
__asm mov [programcounter], AXREG // Put the return address into the variable we'll return

return programcounter;
}
#pragma auto_inline(on)
#endif // defined(_M_IX86) || defined(_M_X64)
得到了調用堆棧,自然要記錄下來。Visual Leak Detector使用一個類似map的數據結構來記錄該信息。這樣可以方便的從requestNumber查找到其調用堆棧。分配鉤子函數的allocType參數表示此次堆內存分配的類型,包括_HOOK_ALLOC, _HOOK_REALLOC, 和 _HOOK_FREE,下面代碼是Visual Leak Detector對各種情況的處理。

switch (type) {
case _HOOK_ALLOC:
visualleakdetector.hookmalloc(request);
break;

case _HOOK_FREE:
visualleakdetector.hookfree(pdata);
break;

case _HOOK_REALLOC:
visualleakdetector.hookrealloc(pdata, request);
break;

default:
visualleakdetector.report("WARNING: Visual Leak Detector: in allochook(): Unhandled allocation type (%d).\n", type);
break;
}
這里,hookmalloc()函數得到當前堆棧,並將當前堆棧與requestNumber加入到類似map的數據結構中。hookfree()函數從類似map的數據結構中刪除該信息。hookrealloc()函數依次調用了hookfree()和hookmalloc()。

檢測內存泄露
前面提到了Visual C++內置的內存泄漏檢測工具的工作原理。與該原理相同,因為全局變數以構造的相反順序析構,在Visual Leak Detector析構時,幾乎所有的其他變數都已經析構,此時如果仍然有未釋放之堆內存,則必為內存泄漏。
分配的堆內存是通過一個鏈表來組織的,檢查內存泄漏則是檢查此鏈表。但是windows沒有提供方法來訪問這個鏈表。Visual Leak Detector使用了一個小技巧來得到它。首先在堆上申請一塊臨時內存,則該內存的地址可以轉換成指向一個_CrtMemBlockHeader結構,在此結構中就可以獲得這個鏈表。代碼如下:
char *pheap = new char;
_CrtMemBlockHeader *pheader = pHdr(pheap)->pBlockHeaderNext;
delete pheap;
其中pheader則為鏈表首指針。

報告生成
前面講了Visual Leak Detector如何檢測、記錄內存泄漏及其其調用堆棧。但是如果要這個信息對程序員有用的話,必須轉換成可讀的形式。Visual Leak Detector使用SymGetLineFromAddr64()及SymFromAddr()生成可讀的報告。
// Iterate through each frame in the call stack.
for (frame = 0; frame < callstack->size(); frame++) {
// Try to get the source file and line number associated with
// this program counter address.
if (pSymGetLineFromAddr64(m_process,
(*callstack)[frame], &displacement, &sourceinfo)) {
...
}

// Try to get the name of the function containing this program
// counter address.
if (pSymFromAddr(m_process, (*callstack)[frame],
&displacement64, pfunctioninfo)) {
functionname = pfunctioninfo->Name;
}
else {
functionname = "(Function name unavailable)";
}
...
}
概括講來,Visual Leak Detector的工作分為3步,首先在初始化注冊一個鉤子函數;然後在內存分配時該鉤子函數被調用以記錄下當時的現場;最後檢查堆內存分配鏈表以確定是否存在內存泄漏並將泄漏內存的現場轉換成可讀的形式輸出。有興趣的讀者可以閱讀Visual Leak Detector的源代碼。

④ 如何檢查內存泄露問題

我在實現過程中,也有點拿不穩,特別是用隊列或棧來存儲樹的結點(也是指針)時,為了確保沒問題,特別是內存的分配,我搜索並安裝了Virtual Leak Detector,一個開源的內存泄漏檢測工具。
初識Visual Leak Detector
靈活自由是C/C++語言的一大特色,而這也為C/C++程 序員出了一個難題。當程序越來越復雜時,內存的管理也會變得越加復雜,稍有不慎就會出現內存問題。內存泄漏是最常見的內存問題之一。內存泄漏如果不是很嚴 重,在短時間內對程序不會有太大的影響,這也使得內存泄漏問題有很強的隱蔽性,不容易被發現。然而不管內存泄漏多麼輕微,當程序長時間運行時,其破壞力是 驚人的,從性能下降到內存耗盡,甚至會影響到其他程序的正常運行。另外內存問題的一個共同特點是,內存問題本身並不會有很明顯的現象,當有異常現象出現時 已時過境遷,其現場已非出現問題時的現場了,這給調試內存問題帶來了很大的難度。< xmlnamespace prefix ="o" />

Visual Leak Detector是一款用於Visual C++的免費的內存泄露檢測工具。可以在http://www.codeproject.com/tools/visualleakdetector.asp 下載到。相比較其它的內存泄露檢測工具,它在檢測到內存泄漏的同時,還具有如下特點:
1、 可以得到內存泄漏點的調用堆棧,如果可以的話,還可以得到其所在文件及行號;
2、 可以得到泄露內存的完整數據;
3、 可以設置內存泄露報告的級別;
4、 它是一個已經打包的lib,使用時無須編譯它的源代碼。而對於使用者自己的代碼,也只需要做很小的改動;
5、 他的源代碼使用GNU許可發布,並有詳盡的文檔及注釋。對於想深入了解堆內存管理的讀者,是一個不錯的選擇。

可見,從使用角度來講,Visual Leak Detector簡單易用,對於使用者自己的代碼,唯一的修改是#include Visual Leak Detector的頭文件後正常運行自己的程序,就可以發現內存問題。從研究的角度來講,如果深入Visual Leak Detector源代碼,可以學習到堆內存分配與釋放的原理、內存泄漏檢測的原理及內存操作的常用技巧等。
本文首先將介紹Visual Leak Detector的使用方法與步驟,然後再和讀者一起初步的研究Visual Leak Detector的源代碼,去了解Visual Leak Detector的工作原理。
< xmlnamespace prefix ="v" />
使用Visual Leak Detector(1.0)
下面讓我們來介紹如何使用這個小巧的工具。
首先從網站上下載zip包,解壓之後得到vld.h, vldapi.h, vld.lib, vldmt.lib, vldmtdll.lib, dbghelp.dll等文件。將.h文件拷貝到Visual C++的默認include目錄下,將.lib文件拷貝到Visual C++的默認lib目錄下,便安裝完成了。因為版本問題,如果使用windows 2000或者以前的版本,需要將dbghelp.dll拷貝到你的程序的運行目錄下,或其他可以引用到的目錄。
註:我下載的是較新版1.9,直接安裝到系統中。因此使用時必須先在VC中設置一下目錄。

接下來需要將其加入到自己的代碼中。方法很簡單,只要在包含入口函數的.cpp文件中包含vld.h就可以。如果這個cpp文件包含了stdafx.h,則將包含vld.h的語句放在stdafx.h的包含語句之後,否則放在最前面。如下是一個示常式序:
#include <vld.h>
void main()
{

}
接下來讓我們來演示如何使用Visual Leak Detector檢測內存泄漏。下面是一個簡單的程序,用new分配了一個int大小的堆內存,並沒有釋放。其申請的內存地址用printf輸出到屏幕上。

編譯運行後,在標准輸出窗口得到:
p=003a89c0

在Visual C++的Output窗口得到:

WARNING: Visual Leak Detector detected memory leaks!
---------- Block 57 at 0x003A89C0: 4 bytes ---------- --57號塊0x003A89C0地址泄漏了4個位元組
Call Stack: --下面是調用堆棧
d:/test/testvldconsole/testvldconsole/main.cpp (7): f --表示在main.cpp第7行的f()函數
d:/test/testvldconsole/testvldconsole/main.cpp (14): main –雙擊以引導至對應代碼處
f:/rtm/vctools/crt_bld/self_x86/crt/src/crtexe.c (586): __tmainCRTStartup
f:/rtm/vctools/crt_bld/self_x86/crt/src/crtexe.c (403): mainCRTStartup
0x7C816D4F (File and line number not available): RegisterWaitForInputIdle
Data: --這是泄漏內存的內容,0x12345678
78 56 34 12 xV4..... ........

Visual Leak Detector detected 1 memory leak.
第二行表示57號塊有4位元組的內存泄漏,地址為0x003A89C0,根據程序控制台的輸出,可以知道,該地址為指針p。程序的第7行,f()函數里,在該地址處分配了4位元組的堆內存空間,並賦值為0x12345678,這樣在報告中,我們看到了這4位元組同樣的內容。
可以看出,對於每一個內存泄漏,這個報告列出了它的泄漏點、長度、分配該內存時的調用堆棧、和泄露內存的內容(分別以16進制和文本格式列出)。雙擊該堆棧報告的某一行,會自動在代碼編輯器中跳到其所指文件的對應行。這些信息對於我們查找內存泄露將有很大的幫助。
這是一個很方便易用的工具,安裝後每次使用時,僅僅需要將它頭文件包含進來重新build就可以。而且,該工具僅在build Debug版的時候會連接到你的程序中,如果build Release版,該工具不會對你的程序產生任何性能等方面影響。所以盡可以將其頭文件一直包含在你的源代碼中。
Visual Leak Detector工作原理
下面讓我們來看一下該工具的工作原理。
在這之前,我們先來看一下Visual C++內置的內存泄漏檢測工具是如何工作的。Visual C++內置的工具CRT Debug Heap工作原來很簡單。在使用Debug版的malloc分配內存時,malloc會在內存塊的頭中記錄分配該內存的文件名及行號。當程序退出時CRT會在main()函數返回之後做一些清理工作,這個時候來檢查調試堆內存,如果仍然有內存沒有被釋放,則一定是存在內存泄漏。從這些沒有被釋放的內存塊的頭中,就可以獲得文件名及行號。
這種靜態的方法可以檢測出內存泄漏及其泄漏點的文件名和行號,但是並不知道泄漏究竟是如何發生的,並不知道該內存分配語句是如何被執行到的。要想了解這些,就必須要對程序的內存分配過程進行動態跟蹤。Visual Leak Detector就是這樣做的。它在每次內存分配時將其上下文記錄下來,當程序退出時,對於檢測到的內存泄漏,查找其記錄下來的上下文信息,並將其轉換成報告輸出。

初始化
Visual Leak Detector要記錄每一次的內存分配,而它是如何監視內存分配的呢?Windows提供了分配鉤子(allocation hooks)來監視調試堆內存的分配。它是一個用戶定義的回調函數,在每次從調試堆分配內存之前被調用。在初始化時,Visual Leak Detector使用_CrtSetAllocHook注冊這個鉤子函數,這樣就可以監視從此之後所有的堆內存分配了。
如何保證在Visual Leak Detector初始化之前沒有堆內存分配呢?全局變數是在程序啟動時就初始化的,如果將Visual Leak Detector作為一個全局變數,就可以隨程序一起啟動。但是C/C++並沒有約定全局變數之間的初始化順序,如果其它全局變數的構造函數中有堆內存分配,則可能無法檢測到。Visual Leak Detector使用了C/C++提供的#pragma init_seg來在某種程度上減少其它全局變數在其之前初始化的概率。根據#pragma init_seg的定義,全局變數的初始化分三個階段:首先是compiler段,一般c語言的運行時庫在這個時候初始化;然後是lib段,一般用於第三方的類庫的初始化等;最後是user段,大部分的初始化都在這個階段進行。Visual Leak Detector將其初始化設置在compiler段,從而使得它在絕大多數全局變數和幾乎所有的用戶定義的全局變數之前初始化。

記錄內存分配
一個分配鉤子函數需要具有如下的形式:
int YourAllocHook( int allocType, void *userData, size_t size, int blockType, long requestNumber, const unsignedchar *filename, int lineNumber);
就像前面說的,它在Visual Leak Detector初始化時被注冊,每次從調試堆分配內存之前被調用。這個函數需要處理的事情是記錄下此時的調用堆棧和此次堆內存分配的唯一標識——requestNumber。
得到當前的堆棧的二進製表示並不是一件很復雜的事情,但是因為不同體系結構、不同編譯器、不同的函數調用約定所產生的堆棧內容略有不同,要解釋堆棧並得到整個函數調用過程略顯復雜。不過windows提供一個StackWalk64函數,可以獲得堆棧的內容。StackWalk64的聲明如下:
BOOL StackWalk64(
DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetMoleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);

STACKFRAME64結構表示了堆棧中的一個frame。給出初始的STACKFRAME64,反復調用該函數,便可以得到內存分配點的調用堆棧了。
// Walk the stack.
while (count < _VLD_maxtraceframes) {
count++;
if (!pStackWalk64(architecture, m_process, m_thread, &frame, &context,
NULL, pSymFunctionTableAccess64, pSymGetMoleBase64, NULL)) {
// Couldn't trace back through any more frames.
break;
}
if (frame.AddrFrame.Offset == 0) {
// End of stack.
break;
}

// Push this frame's program counter onto the provided CallStack.
callstack->push_back((DWORD_PTR)frame.AddrPC.Offset);
}
那麼,如何得到初始的STACKFRAME64結構呢?在STACKFRAME64結構中,其他的信息都比較容易獲得,而當前的程序計數器(EIP)在x86體系結構中無法通過軟體的方法直接讀取。Visual Leak Detector使用了一種方法來獲得當前的程序計數器。首先,它調用一個函數,則這個函數的返回地址就是當前的程序計數器,而函數的返回地址可以很容易的從堆棧中拿到。下面是Visual Leak Detector獲得當前程序計數器的程序:
#if defined(_M_IX86) || defined(_M_X64)
#pragma auto_inline(off)
DWORD_PTR VisualLeakDetector::getprogramcounterx86x64 ()
{
DWORD_PTR programcounter;

__asm mov AXREG, [BPREG + SIZEOFPTR] // Get the return address out of the current stack frame
__asm mov [programcounter], AXREG // Put the return address into the variable we'll return

return programcounter;
}
#pragma auto_inline(on)
#endif // defined(_M_IX86) || defined(_M_X64)
得到了調用堆棧,自然要記錄下來。Visual Leak Detector使用一個類似map的數據結構來記錄該信息。這樣可以方便的從requestNumber查找到其調用堆棧。分配鉤子函數的allocType參數表示此次堆內存分配的類型,包括_HOOK_ALLOC, _HOOK_REALLOC, 和 _HOOK_FREE,下面代碼是Visual Leak Detector對各種情況的處理。

switch (type) {
case _HOOK_ALLOC:
visualleakdetector.hookmalloc(request);
break;

case _HOOK_FREE:
visualleakdetector.hookfree(pdata);
break;

case _HOOK_REALLOC:
visualleakdetector.hookrealloc(pdata, request);
break;

default:
visualleakdetector.report("WARNING: Visual Leak Detector: in allochook(): Unhandled allocation type (%d)./n", type);
break;
}
這里,hookmalloc()函數得到當前堆棧,並將當前堆棧與requestNumber加入到類似map的數據結構中。hookfree()函數從類似map的數據結構中刪除該信息。hookrealloc()函數依次調用了hookfree()和hookmalloc()。

檢測內存泄露
前面提到了Visual C++內置的內存泄漏檢測工具的工作原理。與該原理相同,因為全局變數以構造的相反順序析構,在Visual Leak Detector析構時,幾乎所有的其他變數都已經析構,此時如果仍然有未釋放之堆內存,則必為內存泄漏。
分配的堆內存是通過一個鏈表來組織的,檢查內存泄漏則是檢查此鏈表。但是windows沒有提供方法來訪問這個鏈表。Visual Leak Detector使用了一個小技巧來得到它。首先在堆上申請一塊臨時內存,則該內存的地址可以轉換成指向一個_CrtMemBlockHeader結構,在此結構中就可以獲得這個鏈表。代碼如下:
char *pheap = new char;
_CrtMemBlockHeader *pheader = pHdr(pheap)->pBlockHeaderNext;
delete pheap;
其中pheader則為鏈表首指針。

報告生成
前面講了Visual Leak Detector如何檢測、記錄內存泄漏及其其調用堆棧。但是如果要這個信息對程序員有用的話,必須轉換成可讀的形式。Visual Leak Detector使用SymGetLineFromAddr64()及SymFromAddr()生成可讀的報告。
// Iterate through each frame in the call stack.
for (frame = 0; frame < callstack->size(); frame++) {
// Try to get the source file and line number associated with
// this program counter address.
if (pSymGetLineFromAddr64(m_process,
(*callstack)[frame], &displacement, &sourceinfo)) {
...
}

// Try to get the name of the function containing this program
// counter address.
if (pSymFromAddr(m_process, (*callstack)[frame],
&displacement64, pfunctioninfo)) {
functionname = pfunctioninfo->Name;
}
else {
functionname = "(Function name unavailable)";
}
...
}
概括講來,Visual Leak Detector的工作分為3步,首先在初始化注冊一個鉤子函數;然後在內存分配時該鉤子函數被調用以記錄下當時的現場;最後檢查堆內存分配鏈表以確定是否存在內存泄漏並將泄漏內存的現場轉換成可讀的形式輸出。有興趣的讀者可以閱讀Visual Leak Detector的源代碼。

總結
在使用上,Visual Leak Detector簡單方便,結果報告一目瞭然。在原理上,Visual Leak Detector針 對內存泄漏問題的特點,可謂對症下葯——內存泄漏不是不容易發現嗎?那就每次內存分配是都給記錄下來,程序退出時算總賬;內存泄漏現象出現時不是已時過境 遷,並非當時泄漏點的現場了嗎?那就把現場也記錄下來,清清楚楚的告訴使用者那塊泄漏的內存就是在如何一個調用過程中泄漏掉的。
Visual Leak Detector是一個簡單易用內存泄漏檢測工具。現在最新的版本是1.9a,採用了新的檢測機制,並在功能上有了很多改進。不妨體驗一下

⑤ c++的釋放指針內存空間問題。

像 這個問題吧,,首先要弄清楚 操作系統對堆區是怎麼維護的。
操作系統對堆區的維護 是通過 一個叫做 雙鏈表的 數據結構來進行維護,我們 MALLOC 的時候 其實 是 向這個雙鏈表 中 增加節點。 其結構如下所示:
typedef struct _CrtMemBlockHeader
{
// Pointer to the block allocated just before this one:
struct _CrtMemBlockHeader *pBlockHeaderNext;
// Pointer to the block allocated just after this one:
struct _CrtMemBlockHeader *pBlockHeaderPrev;
char *szFileName; // File name
int nLine; // Line number
size_t nDataSize; // Size of user block
int nBlockUse; // Type of block
long lRequest; // Allocation number
// Buffer just before (lower than) the user's memory:
unsigned char gap[nNoMansLandSize];
} _CrtMemBlockHeader;

這是節點的結構。
MALLOC 一次 就是增加一個 這樣的節點。
如:
00310868 68 65 6C 6C 6F 00 FD FD FD FD AD BA 0D F0 AD BA AB hello..瓠韓
00310879 AB AB AB AB AB AB AB 00 00 00 00 00 00 00 00 DA 28 ..........(
0031088A 16 56 5C 55 00 00 F0 3F 31 00 C4 00 31 00 EE FE EE .V\U...?1...1.鉿.
在310868前面有 32個位元組 的數據 就是我們 上面 的那個結構體的數據成員。
310868處是 我們申請的空間。調用 STRCPY 後,其值被寫為 hello\0 。 最後還有 四個FD 用於越界檢測。

FREE 一次就是從 雙鏈表中 刪除這樣的一個節點。並將 這個節點處的數據 以如下格式 填充: 如:
00310868 EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE 鉿鉿鉿鉿鉿鉿鉿鉿.
00310879 FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE .
0031088A EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE 鉿鉿鉿鉿鉿鉿鉿鉿.

這就 MALLOC 和FREE 的執行過程,不會對 PTR 造成影響 ,PTR現在 依然 指向 310868,
所以我們一般 在FREE(PTR); 後 要加上 PTR=NULL, 來將此指針置空,避免以後使用到它,引起程序崩潰,。 而你沒有 將其置空,反而 對它進行數據寫入 如下:

00310868 77 6F 72 6C 64 37 36 38 39 30 31 32 33 34 35 35 00 world76890123455.
00310879 FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE .
0031088A EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE 鉿鉿鉿鉿鉿鉿鉿鉿.
0031089B FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE .
003108AC EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE 鉿鉿鉿鉿鉿鉿鉿鉿.

這樣 ptr 指向的這個地址 處就又有了數據,,所以輸出可以看到結果。而且 結果 正常,不建議這樣子使用,因為你這一塊內存 已經無法釋放。

以太坊無法連接節點

把你的TCP/IP協議設置成自動獲取狀態試試,方法:右鍵網上鄰居-屬性- 右鍵"本地連接"屬性-雙擊"Internet 協議 TCP/IP"-改為自動獲取

IPX/SPX協議,IPX是NetWare最底層的協議,它只負責數據在網路中的移動,並不保證數據是否傳輸成功,也不提供糾錯服務。IPX在負責數據傳送時,如果接收節點在同一網段內,就直接按該節點的ID將數據傳給它;如果接收節點是遠程的(不在同一網段內,或位於不同的區域網中),數據將交給NetWare伺服器或路由器中的網路ID,繼續數據的下一步傳輸。SPX在整個協議中負責對所傳輸的數據進行無差錯處理,所以我們將IPX/SPX也叫做「Novell的協議集」。

⑦ java Socket客戶端向伺服器端用ObjectOutputStream類的writeUTF後報錯

socket 在操作完之前關閉了,你可以看看socket什麼時候關閉的

⑧ soap11headerblockimpl存在哪個包里

soapheader SOAP標頭 雙語對照 詞典結果: 網路釋義 正文簡介可選的 SOAP Header 元素包含頭部信息。1 SOAP Header 元素 可選的 SOAP Header 元素可包含有關 SOAP 消息的應用程序專用信息(比如認證、支付等)。如果 Header 元素被提供,則它必...

⑨ 什麼是梅克爾樹

梅克爾樹(Merkle trees)是區塊鏈的基本組成部分。雖說從理論上來講,沒有梅克爾樹的區塊鏈當然也是可能的,你只需創建直接包含每一筆交易的巨大區塊頭(block header)就可以實現,但這樣做無疑會帶來可擴展性方面的挑戰,從長遠發展來看,可能最後將只有那些最強大的計算機,才可以運行這些無需受信的區塊鏈。 正是因為有了梅克爾樹,以太坊節點才可以建立運行在所有的計算機、筆記本、智能手機,甚至是那些由Slock.it生產的物聯網設備之上。那麼,究竟梅克爾樹是如何工作的呢,它們又能夠提供些什麼價值呢,現在以及未來的?
首先,咱們先來講點基礎知識。梅克爾樹,一般意義上來講,它是哈希大量聚集數據「塊」(chunk)的一種方式,它依賴於將這些數據「塊」分裂成較小單位(bucket)的數據塊,每一個bucket塊僅包含幾個數據「塊」,然後取每個bucket單位數據塊再次進行哈希,重復同樣的過程,直至剩餘的哈希總數僅變為1:即根哈希(root hash)。

熱點內容
eth兌換usdt庫存 發布:2025-06-28 07:57:36 瀏覽:29
錢包trx轉賬消耗多少能量 發布:2025-06-28 07:51:54 瀏覽:935
布比可信區塊鏈創新總決賽 發布:2025-06-28 07:47:08 瀏覽:239
什麼專業屬於區塊鏈 發布:2025-06-28 07:35:24 瀏覽:318
幣圈跑分和鑽石跑分 發布:2025-06-28 07:27:20 瀏覽:527
揭陽區塊鏈交易平台 發布:2025-06-28 07:27:14 瀏覽:50
數字貨幣可以兌美元嗎 發布:2025-06-28 07:18:13 瀏覽:706
btc網上錢包 發布:2025-06-28 07:13:24 瀏覽:527
比特幣勒索病毒公布私鑰匙 發布:2025-06-28 06:42:55 瀏覽:92
10000個比特幣2010 發布:2025-06-28 06:41:23 瀏覽:388