Access violation in delphi - delphi

In a delphi Application, When I move mouse to a component that has Hint I see this error :
" Access violation at address 00484F3B in module 'Plibrary.exe'. Read of address 0000026C"
Why this happen?
Call Stack:
:758e9617 KERNELBASE.RaiseException + 0x54
:458bf456 System.#UStrCmp
:00407558 #UStrCmp + $2C
Forms.TApplication.SetHint(???)
Forms.TApplication.Idle(???)
Forms.TApplication.HandleMessage
Forms.TApplication.Run Plibrary.Plibrary
:75ca1194 kernel32.BaseThreadInitThunk + 0x12
:7752b3f5 ntdll.RtlInitializeExceptionChain + 0x63
:7752b3c8 ntdll.RtlInitializeExceptionChain + 0x36"
And failing code is in System.pas file at line 17732 : "MOV ESI,[ESP]"
Edit (from comment):
In the remain.pas file at this procedure :
procedure TMainForm.ShowHint(Sender: TObject);
begin
if Length(Application.Hint) > 0 then begin
StatusBar.SimplePanel := True;
StatusBar.SimpleText := Application.Hint; //this line gives error
end else
StatusBar.SimplePanel := False;
end;

Read of address 0000026C
This very low address is indicative of an offset to a member field of a nil object reference. Run under the debugger and make sure the debugger is set to break on exceptions. When it does, you should be able to work out which object reference is nil.
Quite possibly the AV happens in VCL code although it will almost certainly be due to an error in your code. If the debugger doesn't break at a very helpful location, enable Debug DCUs in the project options in order to see the VCL source code at the point where the exception is raised.
The stack trace you provide suggests that the error is in TApplication.SetHint, whilst performing a string comparison. The first line of TApplication.SetHint reads:
if FHint <> Value then
I bet the offset to the FHint of TApplication is $026C and that, somehow, your Application variable is set to nil. That said, I don't understand why the error would not have been raised earlier at Length(Application.Hint). It's quite hard to debug this remotely!
Having looked at the layout of TApplication, I think we can rule out Application being nil. Perhaps FHint itself has somehow been corrupted, or perhaps even Value. I think it's going to take access to the actual code and a debugging environment to track this down.

Based on the information provided in the stacktrace:
TApplication.Idle:
Control := DoMouseIdle;
if FShowHint and (FMouseControl = nil) then
CancelHint;
Application.Hint := GetLongHint(GetHint(Control)); // SetHint is called next:
TApplication.SetHint:
if FHint <> Value then // This is the UStrCmp which fails with a Int overflow
String + IntOverflow -> non terminating string. So the most probable cause is a string without a terminator.
So where does the string come from...
GetHint(Control) searches the control (which is at the places you clicked with the cursor) and its parent for a hint that is not empty.
GetLongHint searches the string for a | and if found, uses the part following the | else it uses the complete string.
UStrCmp, is a long pieces of assembler code, that calls other pieces of assembler code. Some of them can raise the EIntegerOverflow error.
Advise
Use the debugger (with debug dcu's on) to see which string has no terminator (0 character at the end). And if you find it, try to solve it or expand the question if you want some more help from us.

Related

Firebird 3.x error "Attempt to execute an unprepared dynamic SQL statement" in Delphi IBX exception handling?

I am using Delphi 2009 Unicode and Firebird 3.x UTF8/dialect 3 database with IBX components. And now I see that all the exceptions raised from the Firebird SQL procedure and trigger code (e.g. using exception my_exception; statement) are handled by IBX as special Firebird exceptions:
Attempt to execute an unprepared dynamic SQL statement
Error Code: 335544711 SQL Code: -901
IBX does not report the name/code/content of the original Firebird exception. It is quite strange, because Delphi 2009 IBX can handle Firebird 2.1 UTF8/Unicode exceptions without problems. It seems to me that IBX is trying to do some extra steps that are not allowed.
Of course, I know that all the advices to move to other frameworks from the IBX, but we are not living in the ideal world, so, the question is as it is.
Question extended:
After initialization code in the project file (this is IB routine http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/IB_SetIBDataBaseErrorMessages.html):
SetIBDataBaseErrorMessages([ShowSQLCode,ShowIBMessage,ShowSQLMessage]);
I am getting normal error messages from the exceptions that are raised from the triggers, but I am still getting generic 'Attempt to execute...' error message in the case when exception is raised from the SQL procedure.
Question updated:
The generic exception about attempt appears when the procedure is called from the IBX TIBStoredProc, but if stored procedure is called (via select from...) from the TIBDataSet, then the right error message appears. So - there should be problem how TIBStoredProc handles the error messages.
Debug shows, that Delphi IBX code IBSQL.pas contains code:
SQLExecProcedure:
begin
fetch_res := Call(FGDSLibrary.isc_dsql_execute2(StatusVector, TRHandle,
#FHandle, Database.SQLDialect, FSQLParams.AsXSQLDA,
FSQLRecord.AsXSQLDA), False);
if (fetch_res <> 0) then
begin
if (fetch_res <> isc_lock_conflict) then
begin
{ Sometimes a prepared stored procedure appears to get
off sync on the server ....This code is meant to try
to work around the problem simply by "retrying". This
need to be reproduced and fixed.
}
FGDSLibrary.isc_dsql_prepare(StatusVector, TRHandle, #FHandle, 0,
PByte(FProcessedSQL.Text), Database.SQLDialect, nil);
Call(FGDSLibrary.isc_dsql_execute2(StatusVector, TRHandle,
#FHandle, Database.SQLDialect, FSQLParams.AsXSQLDA,
FSQLRecord.AsXSQLDA), True);
end
else
IBDataBaseError; // go ahead and raise the lock conflict
end;
end
and the error message about unprepared statement is raised exactly upon the second execution isc_dsql_execute2(...), so - maybe such second try is not necessary and we can raise Exception IBDataBaseError whenever the fetch_res is not 0? Maybe someone knows why Jeff introduced such second call and what bugs this second call tried to solve?
It appears, that Delphi XE 10.2 code makes the second call only in the specific case:
if (fetch_res = isc_bad_stmt_handle) then
And that makes the erroneous second call rare enough to solve the problem in my question. So, the solution is to replace the initial general condition (fetch_res <> isc_lock_conflict) with the more specific condition (fetch_res = isc_bad_stmt_handle).

DialogBoxParam didn't work on 64-bit platform

I am porting my code to 64-bit platform.but I get a problem with DialogBoxParam.it work fine with 32-bit platform but not 64-bit.I used it like below
DialogBoxParam(Hinstance,MAKEINTRESOURCE(DLG_INPUTBOX),owner,#DialogProc,NativeInt(#info))
DLG_INPUTBOX come from the resource file
unit resource_gui;
interface
CONST
DLG_INPUTBOX = 8810;
DLG_PROGRESS = 8800;
DLG_AREYOUSURE = 8809;
BITMPAT_UNCHECKED = 8804;
BITMPAT_CHECKED = 8805;
{$R DLGRES.res}
here is the dialogpro
function DialogProc(hwndDlg:HWND;uMsg:UINT ;wParam:WPARAM ;lParam:LPARAM ):NativeInt;stdcall;
var
info:Pinfo;
OldEditValue:String;
CanClose:boolean;
begin
Result := EIINT(0);
case uMsg of
WM_INITDIALOG:begin
setWindowLong(hwndDlg,GWL_USERDATA,lParam);
end;
WM_SHOWWINDOW:begin
.......
I set a breakpoint in the WM_INITDIALOG code block but it didn't come in
See if this helps:
DialogBoxParam - works in win32, but doesn‎
I've been changing my code to 64 bit and came across my DialogBox Procedures. The call I made to DialogBoxParam to initialize the dialog box would no longer compile in 64 bit, so I changed my procedures from returning BOOL to returning INT_PTR.
Now when I run my code, my dialog box never shows up.
I put a break point in the DialogBox Procedure and it get:
WM_SETFONT
WM_DESTROY
WM_NCDESTROY
messages in that order. I never receive a WM_INITDIALOG message at all anymore!
My call to DialogBoxParam returns -1 and GetLastError returns 0
I had the exact same problem today. I found that my manifest file had the wrong processor architecture associated with it.
processorArchitecture="x86"
instead of
processorArchitecture="amd64"
Once I fixed that, the dialogbox popped up as expected.

Handling DbExpress Sql Error Code 245

I am trying to build a scheduler application for my semestre exam, and I am interogating the database if a teacher has classes in a certain week, certain day and a certain hour. Is there a way to treat Sql Error Codes in Delphi Xe2 using DBExpress? I have a query performing my interogation(I let the users to select the parameters) on SQL Server2008, and here is the issue; If an user lets one parameter field empty, my application shows the message in the image; well this is not a user friendly way of showing error messages, so I tried to handle the exception without any succes: this is my code that i wrote to query SQL Server:
with DataModule1.QueryV1 do
Try
Close;
SQL.Clear; // clear command sql if there is
SQL.Add ('SELECT * FROM OrarC WHERE IDZi =' +
QuotedStr(LlbZiua.KeyValue)+ 'and IDInterval=' + QuotedStr(LlbIntOrar.KeyValue) +
'and IDSala='+ QuotedStr(EdtIDSala.Text)+ EdtSaptamana.Text);
Open;
except
on E:TDBXError do begin
showmessage('Error!');
end;
End;
on E:TDBXError I have also tried E:EDataBaseError and the result is the same; It would be good to handle the error by the SqlErrorCode returned but I don`t know how to get that.
Run your program under the debugger and observe the actual class of the exception that's raised, or you can get the exception class at runtime with something like:
..
except on E: Exception do
ShowMessage(E.ClassName);
end;
If it is indeed a TDBXError then you could use for example
uses
dbxcommon;
except
on E: TDBxError do begin
if (E.ErrorCode = TDBXErrorCodes.InvalidArgument) then
..
But as far as I can see 245 is not one of TDBXErrorCodes, so possibly you've got an other exception. If it's an EDatabaseError there's nothing much to do, since the class does not have an error code field.
Not quite relevant but also see Data.DBXCommon.TDBXConnection.OnErrorEvent to be able to manage dbexpress exceptions at a central location.

Reconcile Error: Has anyone had problems with truncated error messages?

I'm here again to ask for a help to you. This time I believe that few will respond given the great particularity of the problem which I will relate. I'm starting in the world of DataSnap, and still have things I do not understand how this error I will relate.
My Delphi is XE (version 1, Update1). I am using Postgres which generates error messages in Portuguese (Portuguese Brazil) and for this reason the error messages have accents. The connection components are ZeosLib package.
I am using a dialog box "reconcile error" to display errors arising from the application of updates and to test, I tried to insert a record that already existed, thus violating a unique key and thus displaying the reconcile error dialog.
In the memo of the dialog, the message that appears is truncated, ie cut. Check it out:
ERRO: duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"
DETAIL: Chave (va_login)=(admin) já existe.
CONTEXT: comando SQL "INSERT INTO USUARIOS (VA_NOME
,VA_LOGIN
,CH
But actually what should be returned is this:
ERRO: duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"
DETAIL: Chave (va_login)=(admin) já existe.
CONTEXT: comando SQL "INSERT INTO USUARIOS (VA_NOME
,VA_LOGIN
,CH_SENHA
,VA_EMAIL)
VALUES (pVA_NOME
,pVA_LOGIN
,pCH_SENHA
,pVA_EMAIL)"
PL/pgSQL function "idu_usuarios" line 7 at comando SQL
I have done a debug on the server to see if the problem is ZeosLib, but I found that the error message generated on the server is complete, proving that ZeosLib does not truncate the message. Everything is unicode. All strings are WideString (the default) on both my program and in ZeosLib.
As you know, to be thrown on the server, the exception is forwarded to the client, roughly speaking, by DataSnap, and on the client, the Reconcile method of TClientDataSet verify if there were problems and then throw the famous exception EReconcileError that can be handled in the OnReconcileError event of TClientDataSet, therefore I believe that the message is being truncated by DataSnap.
On the client I debug the Reconcile method (DBClient.pas) and immediately before the exception is thrown the flow enters a function within a cpp source code that I think part of the library midas.dll, MidasLib.obj more specifically, since I am using this strategy, not to have to distribute the DLL with my application.
Check(FDSBase.Reconcile_MD(FReconcileDataSet.FDSBase, FDeltaPacket, VarToDataPacket(Results), Integer(Self), RCB));
This call is done at line 1952 of the unit DBClient.pas on Delphi XE Update1. Pressing F7, the debugger enters a source C++ (cpp), so I believe it is within the midaslib.obj. How I do not understand C++ well, I press Shift-F8 to exit the current method and return the next instruction, that is already inside the event OnReconcileError!! Therefore, the truncation must be done within the function I mentioned, within a cpp source, within midaslib.
My intention is to make the Reconcile Error dialog a tool not only for the final user but to support personals, providing separately information of Error, Details and Context. This helps a lot to discover a problem.
The problem now is to make the message appear in full. Has anyone had this kind of problem with messages being truncated by midas?
Also another point DSClient.pas I could extract the error message as it is passed to the exception:
'Erro SQL: ERRO: duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"'#$A'DETAIL: Chave (va_login)=(admin) já existe.'#$A'CONTEXT: comando SQL "INSERT INTO USUARIOS (VA_NOME'#$A' ,VA_LOGIN'#$A' ,CH'
If you remove the quotes and replace #$A (1 character) by a white space (one character), you will see that the string has exactly 255 characters!!
I also discovered that the "GetErrorString" in dspickle.cpp uses the constant DBIMAXMSGLEN which is defined in bdetypes.h as 127 (half of 255). As we are in the world of Unicode, it would not be a question of increasing this value to 255 in order to have two bytes per character? This is only a guess...
I leave the question in the air because I lack the knowledge to understand C++ :) Who can help, just look at the function implementation "GetErrorString" in dspickle.cpp. There is this:
LoadString((HINSTANCE)hDll, iErrCode, pString, DBIMAXMSGLEN)
pString is the error message and DBIMAXMSGLEN = 127.
Contradicting the opinion of others I decided to tweak further and finally figured out how to increase the number of characters in the "Reconcile" error message. As I thought the problem was in midas.dll, or more specifically the sources that make up the midas dll because the same set of sources can create MidasLib, which does not require a midas dll. To resolve I had to install the Delphi C++ personality to compile the midas.
After finding the line of the error, I discovered that there is even a request for repairs to the QC (http://qc.embarcadero.com/wc/qcmain.aspx?d=84960) which seems to have been ignored by the staff of Embarcadero, as that the "Resolution" as is "Deferred to Next Rel" (Deferred to Next Release) but the request is from 2010 and I'm using Delphi XE which in my opinion should have the solution but here I am correcting by myself ;)
The problem is inside the method "Clone" of the "DSBASE" class, inside source "ds.cpp" at line 2133 (Delphi XE, Update1). Below is the code block. The red line is the problematic line:
// Set the third field for the error string.
LdStrCpy((pCHAR)pFldDes->szName, szdsERRMESSAGE);
pFldDes->iFldType = fldZSTRING;
pFldDes->iUnits1 = 255; // Increased on request.. DBIMAXMSGLEN;
pFldDes++;
Note that it is very interesting the problem line. It has a constant value of 255, which limits the size of the error messages and a comment "Increased on request". Also note that next to the comment, there is a constant DBIMAXMSGLEN, which I had found and already suspected as being responsible for the problem, but as it was not being used I changed the value of DBIMAXMSGLEN but the error message always came without changes. It is worth mentioning that there is a semicolon (;) after DBIMAXMSGLEN which leads me to think that before (I do not know when) this line was one that was just after my fix:
pFldDes->iUnits1 = DBIMAXMSGLEN;
It's as if someone had deliberately set the field value to 255, removing the previous implementation that was really dynamic and seemingly more correct. After performing the replacement of the line I increased the value of DBIMAXMSGLEN to 1024. DBIMAXMSGLEN is declared "bdetypes.h" as a define. After correcting the line went like this:
#define DBIMAXMSGLEN 1024 // Max message len
After these two changes in "ds.cpp" and "bdetypes.h" I build, test, and the result was as expected: the error message was presented in full in the Reconcile dialog.
To the brave who want to try if they have seen this problem, you need the sources of MIDAS, which comes with Delphi from 2010 if I remember correctly. Good luck to all.

Add File Summary tab data in runtime in NTFS in WinXP SP3

I have given up tryng to figure out the reason of this issue, but here is the story and hope you could give a tip...
As I develop unique app ( http://code.google.com/p/sedev ) and therefore I need to polish it.
I have to add File Summary ( very useful info in my opinion ) to any created files by the app, so I decided to go with NTFS compatible structure
edit: code snippet in which problem occurs:
if (FileExists(BaseLocation + LeftStr(GetSSWData, Length(GetSSWData)
- 1) + '.vkp') = True) then // add NTFS descriptive information to output file
try
SetFileSummaryInfo
(PWideChar(BaseLocation + LeftStr(GetSSWData, Length
(GetSSWData) - 1) + '.vkp')); // in my testcase files full path is: C:\Documents and Settings\Kludge\Desktop\sedevrpg\SEDEV_RPG_O_710.vkp
ShowMessagePos('Patch Created successfuly!' + #13#13 +
'Please verify created data to www.se-developers.net.',
ParamStr2X, ParamStr3Y);
MessageBeep(0);
except // exception handler does not even fire on exception ...
on Exception do
begin
if (WarningChBx.Checked = True) then
ShowMessagePos
('Unable to add Description to Output file (' +
BaseLocation + LeftStr(GetSSWData, Length(GetSSWData)
- 1) + '.vkp )', ParamStr2X, ParamStr3Y);
MessageBeep(0);
end;
end
final edit by author: Problem was in SetFileSummaryInfo(PWideChar('')) because after PWideChar conversion you got CHARACTER, not Array of Characters ( aka Strings ) therefore it is not valid path anymore!
Here is main tutorial: http://www.delphipages.com/articles/setting_file_summary_information-9228.html
edit: a better formatted tutorial is here.
BUT, the thing is that I just cannot get that damned FileName param to accept any string ... I have EOleSysError exception: "%1 cannot be found" no matter what.
Faulting operand is:
OleCheck(StgOpenStorageEx(PWideChar(FileName),
STGM_SHARE_EXCLUSIVE or STGM_READWRITE,
STGFMT_ANY,
0, nil, nil, #IID_IPropertySetStorage, stg));
What I do not understand is why it actually wants %1 MSDOS file name input.
I am not launching app from CMD therefore I highly doubt it needs additional param for File path ...
I have tried all possible String and PString conversions, also tried various param passing methods ... It just does not work ...
Any help appreciated!
I can only reproduce your case by specifying an invalid filename. Make sure that you include the full path in your filename.

Resources