文档章节

Delphi 的内存操作函数(1): 给字符指针分配内存

涂孟超
 涂孟超
发布于 2014/09/26 15:38
字数 947
阅读 2
收藏 0
马上能想到的函数有:
GetMem
AllocMem
ReallocMem
FreeMem

GetMemory
ReallocMemory
FreeMemory

New
Dispose

NewStr
DisposeStr

StrNew
StrAlloc
StrDispose

GlobalAllocPtr
GlobalFreePtr

WideStrAlloc
AnsiStrAlloc
StrDispose

Move
MoveMemory
CopyMemory
ZeroMemory
FillMemory
FillChar

StrBufSize

 
 
 
 
 

 

 

  

给字符指针(PChar、PWideChar、PAnsiChar)分配内存, 最佳选择是: StrAlloc.

StrAlloc 虽然最终也是调用了 GetMem, 但 StrAlloc 会在指针前面添加 Delphi 需要的 4 个管理字节(记录长度).

StrAlloc 分配的内存, 用 StrDispose 释放, 用 StrBufSize 获取大小.

用 FreeMem 释放可以吗? 这样会少释放 4 个字节.

这种类型的指针一般用于 API 函数的参数, 譬如获取窗口标题:
var
  p: PChar;
begin
  p := StrAlloc(256);
  GetWindowText(Handle, p, StrBufSize(p));
  ShowMessage(p); {Form1}
  StrDispose(p);
end;

 
 
 
 
 

 

 

  

StrAlloc 根据不同的参数(PWideChar、PAnsiChar)分别重载调用了 WideStrAlloc、AnsiStrAlloc, 所以我们也可以直接使用这两个函数(这也需要用 StrDispose 释放), 不过使用它们的必要性不大; 用 StrAlloc 指定好参数类型即可.

给字符指针分配内存其他方法也挺方便, 譬如:
//获取 WINDOWS 所在目录
var
  buf: array[0..MAX_PATH] of Char;
begin
  GetWindowsDirectory(buf, Length(buf));
  ShowMessage(buf); {C:\WINDOWS}
end;

 
 
 
 
 

 

 

  

数组的内存不是我们自己申请的, 系统会自动释放; 记住: 只要是手动申请的内存一定要手动释放.

我们给字符指针申请内存主要是为了在 API 中接受数据, 如果我们要直接赋给常量值, 系统会自动分配内存的, 譬如:
var
  p: PChar;
begin
  p := '万一的 Delphi 博客';
  ShowMessage(p); {万一的 Delphi 博客}
end;

 
 
 
 
 

 

 

  

当然我们也可以用这种办法申请内存, 就是笨了点, 譬如:
//获取系统目录
var
  p: PChar;
begin
  p := PChar(StringOfChar(Char(0), 256)); {反复一个空字符 256 次成一个字符串, 然后转为 PChar}
  GetSystemDirectory(p, StrBufSize(p));
  ShowMessage(p); {C:\WINDOWS\system32}
end;

 
 
 
 
 

 

 

  

如果在 API 函数需要的字符指针是为了输入, 当然也不需要申请内存, 譬如:
//设置窗口标题
var
  p: PChar;
begin
  p := '窗口新标题';
  SetWindowText(Handle, p);
end;

//也可以直接给常量
begin
  MessageBox(Handle, '提示信息', '标题', MB_OK);
end;

//如果是给字符串的变量或常量, 则需要转换一下
var
  str: string;
begin
  str := '万一的 Delphi 博客';
  TextOut(Canvas.Handle, 10, 10, PChar(str), Length(str));
  {在窗体上输出文字, 此代码不能在 OnCreate 事件中}
end;

 
 
 
 
 

 

 

  

跑题了...到现在已用到了 StrAlloc、StrDispose、WideStrAlloc、AnsiStrAlloc、StrBufSize 几个函数.

还有 NewStr、DisposeStr、StrNew、StrDispose 也貌似有点关系.

先说 NewStr 和 DisposeStr(它们是一对);
NewStr 是根据 AnsiString 再新建一个 PAnsiString, 不过这是为兼容而存在的, Delphi 已不提倡使用了.
不再提倡使用的函数都缀以 deprecated 标识, 并在代码提示中用灰色显示.
其实用 @ 即可获取字符串指针, 当然根本用不着它们.

还有个 StrNew; StrNew 可以再制一个相同的字符指针, 譬如:
var
  p1,p2: PChar;
begin
  p1 := 'Delphi';

  p2 := StrNew(p1);
  ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi}

  p1 := '2009';
  ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi}

  StrDispose(p2); {释放自己申请的}
end;

 
 
 
 
 

 

 

  

不过 StrNew 存在的意义也不大, 我们可以更简单地完成上面的操作:
var
  p1,p2: PChar;
begin
  p1 := 'Delphi';
  p2 := p1;
  ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi}
  p1 := '2009';
  ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi}
end;

 
 
 
 
 

 

 

  

说来说去, 好像只有 StrAlloc 是我们值得我们记忆的?

还有一对非常重要的相关函数: GlobalAllocPtr、GlobalFreePtr; 它们的功能是上面这些都不可替代的!

GlobalAllocPtr 和 GlobalFreePtr 是对系统函数: GlobalAlloc、GlobalFree 的简化, 之所以说它们重要, 只是因为它们可以跨进程操作; 不过 GlobalAllocPtr 是给无类型指针(Pointer)分配内存, 当然就不仅仅用于字符指针了. 还是到后面专题再做例子吧.

本文转载自:http://www.cnblogs.com/del/archive/2008/11/08/1329543.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
用好Delphi中的字符串

用好Delphi中的字符串日期:2005年10月18日 作者: 人气:17184 查看:[大字体 中字体 小字体]一:各种字符串  字符串是Object Pascal所有数据类型中最有用的类型。许多函数以字符串为传递参...

vga
2016/08/09
14
0
Delphi、PChar和Char数组的比较

Delphi、PChar和Char数组的比较   string和Char数组都是一块内存, 其中存放连续的字符. string保存具体字符的内存对用户是透明的, 由Delphi管理它的分配, 复制和释放, 用户不能干预(其实也...

技术小甜
2017/11/08
0
0
delphi pchar char byte string转换问题

delphi pchar char byte string转换问题 注:Delphi中的Char,PChar,PByte,Byte,String的相互转换,您是不是也遇到过,为此头疼过吗?你要是明白了他们的原理就会轻松了。 话题064840的标题是...

鹅倌
2017/01/06
0
0
Delphi 字符串的引用计数与生命周期

先来段代码 type MyString = AnsiString; PMyChar = PAnsiChar; procedure TForm2.Button2Click(Sender: TObject); var p: PMyChar; s, s2: MyString; begin self.Caption := 'frmTest'; //7......

天地弦
2011/10/20
0
0
C语言中的那些库函数(持续更新中)

1.【exit()】 exit是在调用处强行退出程序,运行一次程序就结束。exit(0)表示正常退出。exit(1)表示异常退出,这个1是返回给操作系统的。无论是写在main函数中,还是在其他函数中,都是程序退...

chenyufeng1991
2016/02/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

oh-my-zsh 自定义

GitHub 地址 基于 oh-my-zsh 的自定义配置,增加了一些个人常用插件与皮肤。 采用的是 git submodule 来维护,包括 oh-my-zsh,之所以这么搞,主要是手头有多台 linux 需要维护, 每台机器、...

郁也风
今天
4
0
Docker安装踩坑:E_FAIL 0x80004005的解决

参考 菜鸟教程--Windows Docker 安装 http://www.runoob.com/docker/windows-docker-install.html 官方文档-Install Docker Toolbox on Windows https://docs.docker.com/toolbox/toolbox_in......

karma123
今天
4
0
js垃圾回收机制和引起内存泄漏的操作

JS的垃圾回收机制了解吗? Js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。 JS中最常见的垃圾回收方式是标记清除。 工作原理:是当变量进入环境时,将这个变量标记为“...

Jack088
昨天
17
0
大数据教程(10.1)倒排索引建立

前面博主介绍了sql中join功能的大数据实现,本节将继续为小伙伴们分享倒排索引的建立。 一、需求 在很多项目中,我们需要对我们的文档建立索引(如:论坛帖子);我们需要记录某个词在各个文...

em_aaron
昨天
27
0
"errcode": 41001, "errmsg": "access_token missing hint: [w.ILza05728877!]"

Postman获取微信小程序码的时候报错, errcode: 41001, errmsg: access_token missing hint 查看小程序开发api指南,原来access_token是直接当作parameter的(写在url之后),scene参数一定要...

两广总督bogang
昨天
31
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部