没有高手?怎么一问到指针方面的问题就没人回答了???(0分)

  • 主题发起人 RollingStone
  • 开始时间
R

RollingStone

Unregistered / Unconfirmed
GUEST, unregistred user!
To: 来如风
爽,我太高兴了,我按照您的方法测试了一下,竟然好了,看来老兄是大内一等一高手,
一下子就看出问题症结所在,没有对DELPHI的透彻理解,相信不会有这等眼力,等我
再全面的测试一下,如果问题解决,双手奉上210分:)
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
看来调试技术被很多人忽略了,以至于没有调试的能力了,或者不认为调试是一个能力。
不光是针对本题,很多都是这样,根本就无法定无错误的所在。
来如风,看来你确实是高手了。
 
R

RollingStone

Unregistered / Unconfirmed
GUEST, unregistred user!
感谢 来如风 和其它兄弟们的帖子,让我受益不少。
但是问题还没有得到解决。
现在已经排除了参数这个因素,但是一旦DLL向SQL 2000进行查询,就会出现和原来一样的
错误提示: Invalid Pointer Operation
我们向正确的方向上又前进了一步,但是还没有摘到桃子:)

需要说明的是,我的程序在不使用DLL的情况下,一切正常。现在之所以使用DLL,是因为
我想减少程序文件的大小,使程序更加灵活,所以把主程序的很多功能都分给几个独立的
DLL文件来执行,结果就出现了这个问题。
我计划在这个问题解决之后,我会针对这个问题系统的写一篇文章,以帮助后来的兄弟们
少走弯路。当然,凡是对这个问题有建设性贡献的兄弟,都会出现在文章中:)
 

来如风

Unregistered / Unconfirmed
GUEST, unregistred user!
调试技术我也掌握的不多,

我一般也只是对测试的地方尽量减少测试的关键点,逐个排查

这是最笨也是最简单的方法了,童叟无欺的

解决问题后针对问题写出对策,告示天下,这个主意很好,很是赞成
 
L

lich

Unregistered / Unconfirmed
GUEST, unregistred user!
对象本来就是引用的,干吗还要用对象指针?
只有函数内部创建对象,返回时,才需要传地址的参数,来返回的
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
对于向DLL传递数据库控件计其他指针,是可以的,而且我也曾做过。当然,我用的是
Delphi5。而且在主程序中和DLL中都第一个放上uses ShareMem,否则会出类似Invalid Pointer Operation的错误(时间太久,记不清楚了)。
还有,虽然从参数传递确实没有发现问题,反正我目前还未看出,但确实没有你这么用的!
你好像以前编过C,所以在Delphi中犯了个不伦不类的错误,想传指针,却传了个指针的指针(指针的地址),当然,你在DLL中又还原了。
没有见到这么用的,在Delphi中,是绝对不应该这么用的,这么用,只能说还不了解Delphi。
PQuery=^TQuery//完全多余
procedure FLogin(PqryBasic: PQuery
const UserName, Password, Log: WideString);
改为
procedure FLogin(qryBasic: TQuery
const UserName, Password, Log: WideString);

wr960204说得很正确!
Delphi里所有对象(CLASS)都是通过指针来操作的。PqryBasic本身就是指针了。

TQuery的变量本身就是指针变量
~~~ ~~~~~~~~~~~~




 
R

RollingStone

Unregistered / Unconfirmed
GUEST, unregistred user!
因为这个程序一直都工作正常,所以我没有想到代码会出现问题,现在要把功能分给DLL
完成,就出现了错误。

至于SQL查询语句,这个问题牵涉到的SQL查询语句如下:
////////////////////////////////////////////////////////////////////
{对登陆客户进行身份验证,若合法,则添加他的名字到列表框中,设置FLoggedIn登
陆标志为True。}
procedure FLogin(PqryBasic: PQuery
const UserName, Password, Log: WideString);
var
i: Integer;
begin
if Log='Login' then
with PqryBasic^ do begin
Close;
Sql.Clear;
sql.Append('If Exists (Select UserName from UserDefine where UserName='+ ''''+ UserName+ ''''+ ' and Password='+ ''''+ Password+ ''''+ ')');
Sql.Append('Select 1 as MyLog');
Sql.Append('else Select 0 as MyLog');
Open;
end;
。。。。。。
end
//对登陆客户进行身份验证和离线判断结束。
///////////////////////////////////////////////////////////////////

现在的问题症结在于,DLL在向SQL 2000进行查询的时候,出现了问题。而我用的SQL语句
又找不出问题,如何是好?
 
C

chnplzh

Unregistered / Unconfirmed
GUEST, unregistred user!
你干脆将以下代码放到存储过程里面去算了,调用简单,维护也方便:
Sql.Clear;
sql.Append('If Exists (Select UserName from UserDefine where UserName='+ ''''+ UserName+ ''''+ ' and Password='+ ''''+ Password+ ''''+ ')');
Sql.Append('Select 1 as MyLog');
Sql.Append('else Select 0 as MyLog');
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
这是我以前的一点心得,看看有没有用

小心Delphi的对象,其实Delphi的对象全部是指针,例如我们最熟悉的Form,当我们调用
Form1.Edit1.Text时,其实Form1是指针,Edit1也是指针,只是大家可能没有注意罢了
也许有人会说,不对指针的调用应该是用Pointer^.Member,不错,是这样的,只不过
Form1和Edit1是Class,它是用指针实现,具有指针所有特性,但毕竟定义为Class,所以只能
用Form1.Edit1.Text来调用,而不能用Form1^.Edit^.Text,在这里还有一个有趣的现象,可
能大家没有注意,我们不可以用Edit1^.Text,但是如果我们定义
var pEdit: ^TEdit;
pEdit1 := @Edit1;
结果会怎样呢?如果我们要给Edit1.Text赋值'123',那么我们如何使用pEdit?
大家都会说,简单pEdit1^.Text := '123'就可以了,不错确实是这样,不过大家可以再试
一下,用pEdit1.Text := '123',看看会怎样,没想到吧,结果一样,这就是为什么说
对象就是指针的例子之一,在Delphi中,没有C++那样的对象变量,只要是对象,都用指针
实现。结构变量和结构指针的用法也有类似的地方,不过Record的变量,不是由指针来实
现的
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
>>现在的问题症结在于,DLL在向SQL 2000进行查询的时候,出现了问题。而我用的SQL语句
其实你还是没有定位问题的错误。
如果去掉所有的SQL语句,就相当于没有使用PqryBasic变量,即使PqryBasic是错误的,你也发现不了。
而一旦使用PqryBasic,就出问题,并不能完全说明错误在SQL。
首先用Delphi的方法传递参数。
第二,到底主程序中,你是否有ShareMem?这很重要。
 
R

RollingStone

Unregistered / Unconfirmed
GUEST, unregistred user!
To:SS2000 &amp
lich

您们说的很对,TQuery本身就是指针,我那样做是画蛇添足,我对DELPHI的VCL内幕的确
所知甚少,现在正想练习这方面的内功:)

我刚才按照测试过了,只用'Select 1 as MyLog'一个查询语句,不牵涉到查询SQL 2000
的情况下,一切正常,但是一旦向SQL 2000查询,就出现了这个问题。

另外,SS2000提到的在主程序中加入ShareMem单元,我想这应该是解决长字符串WideString
的问题的,我在DLL的项目文件和单元文件都第一个引用了ShareMem,但是在主程序中,我
第一个引用,编译正常(刚才说的编译错误是笔误),但是在关闭程序的时候,Delphi6就出现"Invalid Pointer Operation"错误。如果不引用,则一切正常。
我的主程序的相关源码如下:
////////////////////////////////////////////////////////////////
//下面是主程序的项目文件Srv.dpr加入ShareMem的相关代码:
unit main;

interface

uses
ShareMem, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ShellAPI, Menus, DB, DBTables;
。。。。。。

//下面是需要引用Basic.dll的主程序中的RDM.pas单元文件的相关代码:
unit RDM;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
ShareMem, Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr,
DBClient, Srv_TLB, StdVcl, Provider, DB, DBTables;
。。。。。。
/////////////////////////////////////////////////////////////////
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
//下面是主程序的项目文件Srv.dpr加入ShareMem的相关代码:
unit main;

interface

uses
ShareMem, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ShellAPI, Menus, DB, DBTables;

你加错了,不是在main单元里加,应该在工程文件里加。
在你的项目文件Srv.dpr中加。
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
TQuery中含有string的成员,所以sharemem不光是解决你的WideString,同样也解决你的TQuery变量。
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
单元文件不必再引用ShareMem
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
>>刚才按照测试过了,只用'Select 1 as MyLog'一个查询语句,
>>不牵涉到查询SQL 2000的情况下,一切正常
其实也可以这么说,只用'Select 1 as MyLog'一个查询语句,
不涉及UserName, Password, Log变量的情况下,一切正常。
所以,同一个现象,结论可以不一样,关键是你怎么分析调试,如何定位!
 
R

RollingStone

Unregistered / Unconfirmed
GUEST, unregistred user!
To: SS2000

在下对您的景仰之情,犹如滔滔江水,连绵不绝:)
现在问题得到彻底解决,我将会很快把210分奉上

虽然问题得到解决,但是我还是不知道这是为什么?不知道为什么,心里总感到不爽,您
能否一帮到底,解释一下,为什么一定要加上ShareMem才能使DLL正常呢?
我想,这不应该是为了解决WideString的问题,因为在我不使用SQL查询的时候,照样是
存在WideString的参数的,可是那时候并没有出问题啊
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
>>刚才按照测试过了,只用'Select 1 as MyLog'一个查询语句,
>>不牵涉到查询SQL 2000的情况下,一切正常
其实用'Select 1 as MyLog'查询语句已经涉及查询SQL 2000,所以
>>不牵涉到查询SQL 2000的情况下,一切正常
这个结论站不住
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
/////////////////////////////////////////////////////////////////////////
以下是主程序调用的Basic.dll的相关代码:
//下面是Basic.dll的项目文件Basic.dpr的相关代码
library Basic;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

仔细读一下 Important 重要!!!
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
>>我想,这不应该是为了解决WideString的问题,因为在我不使用SQL查询的时候,照样是
>>存在WideString的参数的,可是那时候并没有出问题啊

前面我已经解释了

其实也可以这么说,只用'Select 1 as MyLog'一个查询语句,
不涉及UserName, Password, Log变量的情况下,一切正常。
所以,同一个现象,结论可以不一样,关键是你怎么分析调试,如何定位!
 
R

RollingStone

Unregistered / Unconfirmed
GUEST, unregistred user!
To: SS2000

太谢谢您了,我从您这里学习到很多重要的东西,对我受益良多,尤其是一些概念性的东
西,我已经知道为什么了,您是世外高人:)
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
636
import
I
D
回复
0
查看
1K
DelphiTeacher的专栏
D
顶部