问题描述:
创建XML文档对象有时候失败。详细说明:
函数调用关系如下:
BuildLoginCommand //创建登录的XML命令格式文本
┕━ BuildPackageRootNode //创建XML格式的命令基本结构
┕━ NewXMLDoc //创建XML文档对象在执行NewXMLDoc的时候,NewXMLDoc没有任何的参数,仅仅创建一个XML文档对象,然后返回而已。
然而,奇怪的问题出现了,在BuildLoginCommand方法的password参数为某些值的时候,创建对象后,可以看到Result的地址由nil变成一个内存地址,但是,执行下一步属性赋值操作的时候,产生了读写异常。导致程序不响应。例如:
password 的值 = 'cD?[2<HAWb1VH9-KFI<&+GN(XLO[!Kh' 时,会产生异常。
password 的值 = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh' 时,程序正常运行。var
dm: TDataModule;//创建XML文档对象
function NewXMLDoc(): IXMLDocument;
begin
if NOT Assigned( dm ) then
begin
dm := TDataModule.Create( nil );
end;
Result := TXMLDocument.Create( dm ); Result.Active := True; //某些情况下,这儿会出错。产生EAccessViolation异常,然后程序就不响应了。
Result.Version := '1.0';end;//创建XML格式的命令基本结构
function BuildPackageRootNode(cmdName: string): IXMLNode;
var
doc : IXMLDocument;
packageNode: IXMLNode;
commandNode: IXMLNode;
begin
doc := NewXMLDoc();
//doc := NewXMLDocument();
//创建Package根节点
packageNode := doc.CreateNode('Package');
//创建Command子节点
commandNode := packageNode.AddChild('Command');
commandNode.NodeValue := cmdName;
//创建Body子结点
packageNode.AddChild('Body'); Result := packageNode;
end;//创建登录的XML命令格式文本
function BuildLoginCommand(employeeId, password: string): string;
var
packageNode : IXMLNode;
bodyNode : IXMLNode;
employeeIdNode: IXMLNode;
passwordNode : IXMLNode;
begin
//password = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh'
packageNode := BuildPackageRootNode( CMD_CLIENT_LOGIN );
bodyNode := packageNode.ChildNodes['Body']; employeeIdNode := bodyNode.AddChild('EmployeeId');
employeeIdNode.NodeValue := employeeId;
passwordNode := bodyNode.AddChild('Password');
passwordNode.NodeValue := password; Result := packageNode.XML;
end;
创建XML文档对象有时候失败。详细说明:
函数调用关系如下:
BuildLoginCommand //创建登录的XML命令格式文本
┕━ BuildPackageRootNode //创建XML格式的命令基本结构
┕━ NewXMLDoc //创建XML文档对象在执行NewXMLDoc的时候,NewXMLDoc没有任何的参数,仅仅创建一个XML文档对象,然后返回而已。
然而,奇怪的问题出现了,在BuildLoginCommand方法的password参数为某些值的时候,创建对象后,可以看到Result的地址由nil变成一个内存地址,但是,执行下一步属性赋值操作的时候,产生了读写异常。导致程序不响应。例如:
password 的值 = 'cD?[2<HAWb1VH9-KFI<&+GN(XLO[!Kh' 时,会产生异常。
password 的值 = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh' 时,程序正常运行。var
dm: TDataModule;//创建XML文档对象
function NewXMLDoc(): IXMLDocument;
begin
if NOT Assigned( dm ) then
begin
dm := TDataModule.Create( nil );
end;
Result := TXMLDocument.Create( dm ); Result.Active := True; //某些情况下,这儿会出错。产生EAccessViolation异常,然后程序就不响应了。
Result.Version := '1.0';end;//创建XML格式的命令基本结构
function BuildPackageRootNode(cmdName: string): IXMLNode;
var
doc : IXMLDocument;
packageNode: IXMLNode;
commandNode: IXMLNode;
begin
doc := NewXMLDoc();
//doc := NewXMLDocument();
//创建Package根节点
packageNode := doc.CreateNode('Package');
//创建Command子节点
commandNode := packageNode.AddChild('Command');
commandNode.NodeValue := cmdName;
//创建Body子结点
packageNode.AddChild('Body'); Result := packageNode;
end;//创建登录的XML命令格式文本
function BuildLoginCommand(employeeId, password: string): string;
var
packageNode : IXMLNode;
bodyNode : IXMLNode;
employeeIdNode: IXMLNode;
passwordNode : IXMLNode;
begin
//password = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh'
packageNode := BuildPackageRootNode( CMD_CLIENT_LOGIN );
bodyNode := packageNode.ChildNodes['Body']; employeeIdNode := bodyNode.AddChild('EmployeeId');
employeeIdNode.NodeValue := employeeId;
passwordNode := bodyNode.AddChild('Password');
passwordNode.NodeValue := password; Result := packageNode.XML;
end;
XMLDocument1.Encoding 不知道行不
修改了一下,比较一下区别
function BuildLoginCommand(employeeId, password: string): string;implementation
//创建XML文档对象
function NewXMLDoc(): IXMLDocument;
begin
Result := TXMLDocument.Create( nil);//不要为它弄个OWNER对象
Result.Active := True;
Result.Version := '1.0';
end;//创建XML格式的命令基本结构
function BuildPackageRootNode(doc:IXMLDocument;cmdName: string): IXMLNode;
var
packageNode: IXMLNode;
commandNode: IXMLNode;
begin
//创建Package根节点
packageNode := doc.CreateNode('Package');
//创建Command子节点
commandNode := packageNode.AddChild('Command');
commandNode.NodeValue := cmdName;
//创建Body子结点
packageNode.AddChild('Body'); Result := packageNode;
end;//创建登录的XML命令格式文本
function BuildLoginCommand(employeeId, password: string): string;
var
packageNode : IXMLNode;
bodyNode : IXMLNode;
employeeIdNode: IXMLNode;
passwordNode : IXMLNode; doc:IXMLDocument;
const
CMD_CLIENT_LOGIN='login';
begin
//password = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh'
doc:=NewXMLDoc; packageNode := BuildPackageRootNode(doc, CMD_CLIENT_LOGIN );
bodyNode := packageNode.ChildNodes['Body']; employeeIdNode := bodyNode.AddChild('EmployeeId');
employeeIdNode.NodeValue := employeeId;
passwordNode := bodyNode.AddChild('Password');
passwordNode.NodeValue := password; Result := packageNode.XML;
end;
commandNode := packageNode.AddChild('Command'); //执行这句的时候出现灾难性故障。----------请问,我的代码的并发问题在哪儿?我怎么没看到呢?
你是说的这个doc么?----------
需要说明的是,令我最费解的是,我的代码中
password 的值 = 'cD?[2<HAWb1VH9-KFI<&+GN(XLO[!Kh' 时,总是会产生异常。
password 的值 = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh' 时,程序一直正常运行。创建 IXMLDocument 对象的时候,怎么会受这个 password 的值影响了?
begin
if NOT Assigned( dm ) then
begin
dm := TDataModule.Create( nil );
end;
Result := TXMLDocument.Create( dm ); Result.Active := True; //某些情况下,这儿会出错。产生EAccessViolation异常,然后程序就不响应了。
Result.Version := '1.0';end;
-----------------------
Result.Active := True; //这里就是 password 的值等于某些值的时候,引起的EAccessViolation异常,当时程序不响应。
Result := TXMLDocument.Create( dm );//这样创建的XMLDOCUMENT你什么是去释放呢?于是,我将其改为
Result := TXMLDocument.Create( nil);//
当然,只改这一处地方是不行的...看接下来第2点:
2,function BuildPackageRootNode(cmdName: string): IXMLNode;
var
doc : IXMLDocument;//楼主这儿是个局部变量来引用XMLDOC这儿是接着必须修改的地方.
当这个函数返回时,也就是在BuildLoginCommand函数这一层中,
doc变量会被释放...这就影响到XmlDocument对象的生存期.
于是我整理了一下楼主的代码,让TXMLDOCUMENT对象的创建与释放简单明显化些.
改在BuildLoginCommand中创建XMLDOCUMENT对象.
改成 BuildPackageRootNode(var doc:IXMLDocument;cmdName: string): IXMLNode;
就好了,不然还是灾难性故障,doc还是什么都没有。我是做C#的,偶然用一下Delphi写客户端的WindowsForm,没想到这么不习惯。
按照我的思维,BuildPackageRootNode 返回的是 packageNode,如果他的 parent 是这个方法中的局部变量,存在一个引用关系也不会消失,所以说它的parent也不该消失才对。应该不会存在你所说的生存周期才对呀?直到对packageNode的引用为0,释放资源的时候,才会释放你所说的doc啊!