pchar,pwidechar,pansichar作为返回参数时内存访问错误
生活随笔
收集整理的這篇文章主要介紹了
pchar,pwidechar,pansichar作为返回参数时内存访问错误
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
function Test:pachr; varstr: string;
beginstr := 'Test Char';result:=pchar(str);
end;
上面的Test函數(shù)作為導(dǎo)出函數(shù)時候會出現(xiàn)訪問野指針,因?yàn)閟tr已經(jīng)被釋放了;
方法一:改成全局變量保存的話,可以正常訪問到數(shù)據(jù)
var
DataStore:String; function Test:pachr; varstr: string; beginstr := 'Test Char'; DataStore:=str; ? result:=pchar(DataStore); end;
方法二:給字符指針分配內(nèi)存 function Test:pachr; varstr: string; beginstr := 'Test Char';
以下是萬一的博客中關(guān)于字符串分配內(nèi)存
萬一的博客 http://www.cnblogs.com/del/archive/2008/11/08/1329543.html
馬上能想到的函數(shù)有:
GetMem AllocMem ReallocMem FreeMemGetMemory ReallocMemory FreeMemoryNew DisposeNewStr DisposeStrStrNew StrAlloc StrDisposeGlobalAllocPtr GlobalFreePtrWideStrAlloc AnsiStrAlloc StrDisposeMove MoveMemory CopyMemory ZeroMemory FillMemory FillCharStrBufSize
給字符指針(PChar、PWideChar、PAnsiChar)分配內(nèi)存, 最佳選擇是: StrAlloc.
StrAlloc 雖然最終也是調(diào)用了 GetMem, 但 StrAlloc 會在指針前面添加 Delphi 需要的 4 個管理字節(jié)(記錄長度).
StrAlloc 分配的內(nèi)存, 用 StrDispose 釋放, 用 StrBufSize 獲取大小.
用 FreeMem 釋放可以嗎? 這樣會少釋放 4 個字節(jié).
這種類型的指針一般用于 API 函數(shù)的參數(shù), 譬如獲取窗口標(biāo)題:
varp: PChar; beginp := StrAlloc(256);GetWindowText(Handle, p, StrBufSize(p));ShowMessage(p); {Form1}StrDispose(p); end;
StrAlloc 根據(jù)不同的參數(shù)(PWideChar、PAnsiChar)分別重載調(diào)用了 WideStrAlloc、AnsiStrAlloc, 所以我們也可以直接使用這兩個函數(shù)(這也需要用 StrDispose 釋放), 不過使用它們的必要性不大; 用 StrAlloc 指定好參數(shù)類型即可.
給字符指針分配內(nèi)存其他方法也挺方便, 譬如:
//獲取 WINDOWS 所在目錄 varbuf: array[0..MAX_PATH] of Char; beginGetWindowsDirectory(buf, Length(buf));ShowMessage(buf); {C:\WINDOWS} end;
數(shù)組的內(nèi)存不是我們自己申請的, 系統(tǒng)會自動釋放; 記住: 只要是手動申請的內(nèi)存一定要手動釋放.
我們給字符指針申請內(nèi)存主要是為了在 API 中接受數(shù)據(jù), 如果我們要直接賦給常量值, 系統(tǒng)會自動分配內(nèi)存的, 譬如:
varp: PChar; beginp := '萬一的 Delphi 博客';ShowMessage(p); {萬一的 Delphi 博客} end;
當(dāng)然我們也可以用這種辦法申請內(nèi)存, 就是笨了點(diǎn), 譬如:
//獲取系統(tǒng)目錄 varp: PChar; beginp := PChar(StringOfChar(Char(0), 256)); {反復(fù)一個空字符 256 次成一個字符串, 然后轉(zhuǎn)為 PChar}GetSystemDirectory(p, StrBufSize(p));ShowMessage(p); {C:\WINDOWS\system32} end;
如果在 API 函數(shù)需要的字符指針是為了輸入, 當(dāng)然也不需要申請內(nèi)存, 譬如:
//設(shè)置窗口標(biāo)題 varp: PChar; beginp := '窗口新標(biāo)題';SetWindowText(Handle, p); end;//也可以直接給常量 beginMessageBox(Handle, '提示信息', '標(biāo)題', MB_OK); end;//如果是給字符串的變量或常量, 則需要轉(zhuǎn)換一下 varstr: string; beginstr := '萬一的 Delphi 博客';TextOut(Canvas.Handle, 10, 10, PChar(str), Length(str));{在窗體上輸出文字, 此代碼不能在 OnCreate 事件中} end;
跑題了...到現(xiàn)在已用到了 StrAlloc、StrDispose、WideStrAlloc、AnsiStrAlloc、StrBufSize 幾個函數(shù).
還有 NewStr、DisposeStr、StrNew、StrDispose 也貌似有點(diǎn)關(guān)系.
先說 NewStr 和 DisposeStr(它們是一對);?
NewStr 是根據(jù) AnsiString 再新建一個 PAnsiString, 不過這是為兼容而存在的, Delphi 已不提倡使用了.
不再提倡使用的函數(shù)都綴以 deprecated 標(biāo)識, 并在代碼提示中用灰色顯示.
其實(shí)用 @ 即可獲取字符串指針, 當(dāng)然根本用不著它們.
還有個 StrNew; StrNew 可以再制一個相同的字符指針, 譬如:
varp1,p2: PChar; beginp1 := 'Delphi';p2 := StrNew(p1);ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi}p1 := '2009';ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi}StrDispose(p2); {釋放自己申請的} end;
不過 StrNew 存在的意義也不大, 我們可以更簡單地完成上面的操作:
varp1,p2: PChar; beginp1 := 'Delphi';p2 := p1;ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi}p1 := '2009';ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi} end;
說來說去, 好像只有 StrAlloc 是我們值得我們記憶的?
還有一對非常重要的相關(guān)函數(shù): GlobalAllocPtr、GlobalFreePtr; 它們的功能是上面這些都不可替代的!
GlobalAllocPtr 和 GlobalFreePtr 是對系統(tǒng)函數(shù): GlobalAlloc、GlobalFree 的簡化, 之所以說它們重要, 只是因?yàn)樗鼈兛梢钥邕M(jìn)程操作; 不過 GlobalAllocPtr 是給無類型指針(Pointer)分配內(nèi)存, 當(dāng)然就不僅僅用于字符指針了. 還是到后面專題再做例子吧.
end;
上面的Test函數(shù)作為導(dǎo)出函數(shù)時候會出現(xiàn)訪問野指針,因?yàn)閟tr已經(jīng)被釋放了;
方法一:改成全局變量保存的話,可以正常訪問到數(shù)據(jù)
var
DataStore:String; function Test:pachr; varstr: string; beginstr := 'Test Char'; DataStore:=str; ? result:=pchar(DataStore); end;
方法二:給字符指針分配內(nèi)存 function Test:pachr; varstr: string; beginstr := 'Test Char';
Result:=StrAlloc(Length(str)+1);
StrPcopy(Result,str);
end;以下是萬一的博客中關(guān)于字符串分配內(nèi)存
萬一的博客 http://www.cnblogs.com/del/archive/2008/11/08/1329543.html
Delphi 的內(nèi)存操作函數(shù)(1): 給字符指針分配內(nèi)存
馬上能想到的函數(shù)有:
GetMem AllocMem ReallocMem FreeMemGetMemory ReallocMemory FreeMemoryNew DisposeNewStr DisposeStrStrNew StrAlloc StrDisposeGlobalAllocPtr GlobalFreePtrWideStrAlloc AnsiStrAlloc StrDisposeMove MoveMemory CopyMemory ZeroMemory FillMemory FillCharStrBufSize
給字符指針(PChar、PWideChar、PAnsiChar)分配內(nèi)存, 最佳選擇是: StrAlloc.
StrAlloc 雖然最終也是調(diào)用了 GetMem, 但 StrAlloc 會在指針前面添加 Delphi 需要的 4 個管理字節(jié)(記錄長度).
StrAlloc 分配的內(nèi)存, 用 StrDispose 釋放, 用 StrBufSize 獲取大小.
用 FreeMem 釋放可以嗎? 這樣會少釋放 4 個字節(jié).
這種類型的指針一般用于 API 函數(shù)的參數(shù), 譬如獲取窗口標(biāo)題:
varp: PChar; beginp := StrAlloc(256);GetWindowText(Handle, p, StrBufSize(p));ShowMessage(p); {Form1}StrDispose(p); end;
StrAlloc 根據(jù)不同的參數(shù)(PWideChar、PAnsiChar)分別重載調(diào)用了 WideStrAlloc、AnsiStrAlloc, 所以我們也可以直接使用這兩個函數(shù)(這也需要用 StrDispose 釋放), 不過使用它們的必要性不大; 用 StrAlloc 指定好參數(shù)類型即可.
給字符指針分配內(nèi)存其他方法也挺方便, 譬如:
//獲取 WINDOWS 所在目錄 varbuf: array[0..MAX_PATH] of Char; beginGetWindowsDirectory(buf, Length(buf));ShowMessage(buf); {C:\WINDOWS} end;
數(shù)組的內(nèi)存不是我們自己申請的, 系統(tǒng)會自動釋放; 記住: 只要是手動申請的內(nèi)存一定要手動釋放.
我們給字符指針申請內(nèi)存主要是為了在 API 中接受數(shù)據(jù), 如果我們要直接賦給常量值, 系統(tǒng)會自動分配內(nèi)存的, 譬如:
varp: PChar; beginp := '萬一的 Delphi 博客';ShowMessage(p); {萬一的 Delphi 博客} end;
當(dāng)然我們也可以用這種辦法申請內(nèi)存, 就是笨了點(diǎn), 譬如:
//獲取系統(tǒng)目錄 varp: PChar; beginp := PChar(StringOfChar(Char(0), 256)); {反復(fù)一個空字符 256 次成一個字符串, 然后轉(zhuǎn)為 PChar}GetSystemDirectory(p, StrBufSize(p));ShowMessage(p); {C:\WINDOWS\system32} end;
如果在 API 函數(shù)需要的字符指針是為了輸入, 當(dāng)然也不需要申請內(nèi)存, 譬如:
//設(shè)置窗口標(biāo)題 varp: PChar; beginp := '窗口新標(biāo)題';SetWindowText(Handle, p); end;//也可以直接給常量 beginMessageBox(Handle, '提示信息', '標(biāo)題', MB_OK); end;//如果是給字符串的變量或常量, 則需要轉(zhuǎn)換一下 varstr: string; beginstr := '萬一的 Delphi 博客';TextOut(Canvas.Handle, 10, 10, PChar(str), Length(str));{在窗體上輸出文字, 此代碼不能在 OnCreate 事件中} end;
跑題了...到現(xiàn)在已用到了 StrAlloc、StrDispose、WideStrAlloc、AnsiStrAlloc、StrBufSize 幾個函數(shù).
還有 NewStr、DisposeStr、StrNew、StrDispose 也貌似有點(diǎn)關(guān)系.
先說 NewStr 和 DisposeStr(它們是一對);?
NewStr 是根據(jù) AnsiString 再新建一個 PAnsiString, 不過這是為兼容而存在的, Delphi 已不提倡使用了.
不再提倡使用的函數(shù)都綴以 deprecated 標(biāo)識, 并在代碼提示中用灰色顯示.
其實(shí)用 @ 即可獲取字符串指針, 當(dāng)然根本用不著它們.
還有個 StrNew; StrNew 可以再制一個相同的字符指針, 譬如:
varp1,p2: PChar; beginp1 := 'Delphi';p2 := StrNew(p1);ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi}p1 := '2009';ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi}StrDispose(p2); {釋放自己申請的} end;
不過 StrNew 存在的意義也不大, 我們可以更簡單地完成上面的操作:
varp1,p2: PChar; beginp1 := 'Delphi';p2 := p1;ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi}p1 := '2009';ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi} end;
說來說去, 好像只有 StrAlloc 是我們值得我們記憶的?
還有一對非常重要的相關(guān)函數(shù): GlobalAllocPtr、GlobalFreePtr; 它們的功能是上面這些都不可替代的!
GlobalAllocPtr 和 GlobalFreePtr 是對系統(tǒng)函數(shù): GlobalAlloc、GlobalFree 的簡化, 之所以說它們重要, 只是因?yàn)樗鼈兛梢钥邕M(jìn)程操作; 不過 GlobalAllocPtr 是給無類型指針(Pointer)分配內(nèi)存, 當(dāng)然就不僅僅用于字符指針了. 還是到后面專題再做例子吧.
轉(zhuǎn)載于:https://www.cnblogs.com/h2zZhou/p/10043972.html
總結(jié)
以上是生活随笔為你收集整理的pchar,pwidechar,pansichar作为返回参数时内存访问错误的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: apache开启.htaccess
- 下一篇: 单反相机操作入门