关于Delphi中指针使用的心得
前段时间一直在搞一个项目,常用到ListView,而且常把Record放入ItemData。一开始我就把对ListView的常规操作都写入一个Dll(包括批量的添加数据,保存数据,加载数据),方便于以后的使用。这是恶梦的开始。
这样做不要紧,等项目越做越深入时,越来越多的问题突现。只要对ListView操作不管什么操作,添加、删除,就是点击某行,就会跳出“Invalid pointer operation”,或者“Access violation ”某个地址错误。这使得我的项目进程大大受限,最后不得不停下来专心解决这个问题。
一开始,我并不认为是调用DLL时的问题,当我把其它一些功能层层剥离时发现,就连LoadLibrary('8888.dll');都会出错。最后不得不把注意力放在操作ListView的DLL中。
这个DLL中有这样一段代码
1
function SetSubColumns( var Xml: IXMLDocument;
2
AddNodeName: WideString;
3
var ColumnsField : TStringList;
4
var Lv: TListView ):Boolean;stdcall;
5
var
6
ListItem : TListItem;
7
DataNode: IXMLNode;
8
NodeList: IXMLNodeList;
9
HideStr : PItemData;
10
i,j: Integer;
11
begin
12
try
13
NodeList := Xml.DocumentElement.ChildNodes;
14
for i := 0 to NodeList.Count - 1 do
15
begin
16
ListItem := Lv.Items.Add;
17
DataNode := NodeList[i];
18
{用指针HideStr来保存隐藏的ID}
19
New(HideStr);
20
HideStr.PrimaryKey := StrToInt(DataNode.ChildNodes[ColumnsField[0]].NodeValue);
21
ListItem.Data := HideStr;
22![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
23
ListItem.Caption := DataNode.ChildNodes[ColumnsField[1]].NodeValue;
24![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
25
for j := 2 to ColumnsField.Count - 1 do
26
ListItem.SubItems.Add(DataNode.ChildNodes[ColumnsField[j]].NodeValue);
27![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
28
end;
29
Result:= True;
30
except
31
Result:= False;
32
end;
33
end;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
其中有一段代码为New(HideStr);为ItemData分配内存,这才是问题的所在。语法本身是没有任何问题,但是放错了地方,因为我调用这个DLL时是动态调用,执行完后直接FreeLibrary了,当FreeLibrary时,同时也释放了ItemData所对应的内存地址。所以第一次操作ListView时没有任何问题,第二次操作时就错误百出。
解决的方法有只有一个,就是把分配内存的操作放入主线程,不要放入DLL中。
总结,对于分配内存的操作还是由主程序(主线程)来分配,这样操作起来方便而且不会出错,当主程序关闭时,会一起把分配的内存释放掉。真是吃一堑长一智啊。
好的代码像粥一样,都是用时间熬出来的