Delphi JCL Debug missing stack frame entries for JDBG - delphi

I use following code to dump stack frame at the moment of an exception:
...
var
FTraceList: TStringList;
...
procedure TTraceForm.LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean);
begin
...
StackList := JclCreateStackList(false, 0, Caller(0, false));
try
FTraceList.Add('');
FTraceList.Add('Stack trace at the moment of the exception:');
StackList.AddToStrings(FTraceList, true, true, true, true);
finally
Stacklist.Free;
end;
end;
But it behaves differently in Debug and Release mode.
For an intended exception (exception for testing purposes) in main form's OnKeyDown when compiling in Debug mode (Delphi debug info) the result is:
Stack trace at the moment of the exception:
(00591276){Main.exe } [00992276] DlgTraceException.TTraceForm.LogException (Line 162, "DlgTraceException.pas" + 55) + $4
(0058B8FF){Main.exe } [0098C8FF] JclDebug.JclCreateStackList + $17
(00591281){Main.exe } [00992281] DlgTraceException.TTraceForm.LogException (Line 162, "DlgTraceException.pas" + 55) + $F
(00582AE3){Main.exe } [00983AE3] JclHookExcept.TNotifierItem.DoNotify + $43
(00582CCB){Main.exe } [00983CCB] JclHookExcept.DoExceptNotify + $CF
(00582DAD){Main.exe } [00983DAD] JclHookExcept.HookedExceptObjProc + $1D
(0000606F){Main.exe } [0040706F] System.#HandleAnyException + $33
(00598DE3){Main.exe } [00999DE3] Main.TMainForm.FormKeyDown (Line 658, "Main.pas" + 2) + $7
And this I get in Release mode (JCL debug info added to binary with JCL Debug Expert):
Stack trace at the moment of the exception:
(0053BA27){Main.exe } [0093CA27] DlgTraceException.TTraceForm.LogException + $377
(00536427){Main.exe } [00937427] JclDebug.JclCreateStackList + $17
(0053BA32){Main.exe } [0093CA32] DlgTraceException.TTraceForm.LogException + $382
(0052D60B){Main.exe } [0092E60B] JclHookExcept.TNotifierItem.DoNotify + $43
(0052D7F3){Main.exe } [0092E7F3] JclHookExcept.DoExceptNotify + $CF
(0052D8D5){Main.exe } [0092E8D5] JclHookExcept.HookedExceptObjProc + $1D
(0000606F){Main.exe } [0040706F] System.#HandleAnyException + $33
In second case FormKeyDown entry is missing. Is there somebody who knows why this is happening? I would like to know the entire stack trace in release mode as well.

After playing a bit with compiler options (toggling them on and off) I could isolate the cause. The stack frame has been optimized out. When I turned Optimization off the FormKeyDown call was recorded even in Release mode. The Stack Frames generation option mentioned in comments above did not influence the results.
Of course I'll keep optimizations on in release mode. It will be harder to find the cause of the exception but there is other info about it JCL debug provides which should be (hopefully) sufficient to find the cause of the exception.

Related

What can it be that causes the error "List index out of bounds (..)" after upgrading from Delphi 11.1 to 11.2?

Only since the upgrade I got the subjected error, and after pressing the Details-button in the error message it shows:
[6F6A815B]{rtl280.bpl } System.Classes.TList.Get (Line 5108, "System.Classes.pas" + 2) + $A
[7119EC97]{vcl280.bpl } Vcl.AppEvnts.TMultiCaster.GetAppEvents (Line 686, "Vcl.AppEvnts.pas" + 1) + $B
[7119E5BE]{vcl280.bpl } Vcl.AppEvnts.TMultiCaster.DoActivate (Line 438, "Vcl.AppEvnts.pas" + 5) + $9
[7114362F]{vcl280.bpl } Vcl.Forms.TApplication.WndProc (Line 11035, "Vcl.Forms.pas" + 140) + $C
[6F6C580C]{rtl280.bpl } System.Classes.StdWndProc (Line 18490, "System.Classes.pas" + 8) + $0
[71D85883]{vclide280.bpl} IDEVirtualTrees.TVirtualTreeHintWindow.IsHintMsg (Line 7121, "IDEVirtualTrees.pas" + 7) + $13
[7114417F]{vcl280.bpl } Vcl.Forms.TApplication.ProcessMessage (Line 11460, "Vcl.Forms.pas" + 23) + $1
[711441C2]{vcl280.bpl } Vcl.Forms.TApplication.HandleMessage (Line 11490, "Vcl.Forms.pas" + 1) + $4
[71144501]{vcl280.bpl } Vcl.Forms.TApplication.Run (Line 11629, "Vcl.Forms.pas" + 27) + $3
[00B98082]{bds.exe } bds.bds (Line 227, "" + 16) + $2
I did not add any code since my programs run normally, except when exiting the error appears. Apparently, at that point the debugger is already closed.
Apart from a series of GetIt libraries and components, Spring4D is the only third-party software from an external source.
The GetIt plugins:
Bookmarks-11-1.6.3
Essentials-2022.06-D11
JEDICodeLibraryJCL-2022.02
JEDIVisualComponentLibraryJVCL-2022.02
LockBox-2021.11-11
ParallelDebugger-11-1.0.3
ParnassusCoreEditor-11-1.6.3
PNGComponents-2021.11-11
PowerPDF-2021.09-11
Python4Delphi-1.0
Embarcadero keep backward compatibility in runtime bpls, but made changes into design time bpls when doing minor upgrading from 11.1 to 11.2. Seems like you have installed some third party components, which were not rebuilt for the 11.2 version. Take your time. Developers will rebuild it or Embarcadero will make some patch to fix it.

ClientDataSet's Savetostream with dfxml parameter throws access violation

Opened clientDataSet and getting:
cds.XMLData
or
st_pom := TMemoryStream.Create;
cds.SaveToStream(st_pom, dfXML );
results in AV. Has anyone encountered such behaviour?
I CAN ADD that cds has two fields: numeric and NVarchar(max) ..
It seems as the second field is the problem ...
Here are the last traces after which AV occurs
'{ Original Exception - Access violation at address 4DB10D54. Write of address 05017000 }'
(0002FD54) [4DB10D54]'#$D#$A'(000B2CB3) [004B3CB3] DBClient.TCustomClientDataSet.SaveDataPacket (Line 1500, "DBClient.pas" + 5) + $15'
(000B4385) [004B5385] DBClient.TCustomClientDataSet.WriteDataPacket (Line 2119, "DBClient.pas" + 5) + $6'
(000B457B) [004B557B] DBClient.TCustomClientDataSet.SaveToStream (Line 2186, "DBClient.pas" + 1) + $C'

activeX control crash on alt+tab

I've implemented an Delphi acitveX control. Everything runs fine on html. After that, I embed that activeX in an MFC application. It's good, except that when I test it, if I alt+tab to another windows(Chrome, for example...) and alt+tab back to my application, it just crashed.
I know that this is a non-clear question, but I have no clues. Any clues to solve this situation? What may go wrong or what events I should take a look at?
Thanks.
Edit 1:
This is what I got when I use spy++ on it.
<04518> 00100B7C S WM_ACTIVATE fActive:WA_INACTIVE fMinimized:False hwndPrevious:(null)
<04519> 00100B7C S WM_ACTIVATETOPLEVEL fActive:False dwThreadID:0025F40C
<04520> 00100B7C R WM_ACTIVATETOPLEVEL
Edit 2:
This is what I got from call stack when I break all at the time it hangs
mfc100d.dll!CThreadSlotData::GetThreadValue(int nSlot) Line 248 C++
mfc100d.dll!CThreadLocalObject::GetData(CNoTrackObject * (void)* pfnCreateObject) Line 420 + 0x11 bytes C++
mfc100d.dll!CThreadLocal<AFX_MODULE_THREAD_STATE>::GetData() Line 179 + 0xd bytes C++
mfc100d.dll!AfxGetModuleThreadState() Line 477 + 0x11 bytes C++
mfc100d.dll!afxMapHWND(int bCreate) Line 289 + 0x5 bytes C++
mfc100d.dll!CWnd::FromHandlePermanent(HWND__ * hWnd) Line 324 + 0x7 bytes C++
mfc100d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 405 + 0x9 bytes C++
mfc100d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 420 + 0x15 bytes C++
Edit 3:
I'm using Visual studio 2010, the call stack tell that application hangs in this function, line 2, from afxtls.cpp. Please anyone shed some lights on how to solve this.
inline void* CThreadSlotData::GetThreadValue(int nSlot)
{
EnterCriticalSection(&m_sect);
ASSERT(nSlot != 0 && nSlot < m_nMax);
ASSERT(m_pSlotData != NULL);
ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED);
ASSERT(m_tlsIndex != (DWORD)-1);
if( nSlot <= 0 || nSlot >= m_nMax ) // check for retail builds.
{
LeaveCriticalSection(&m_sect);
return NULL;
}
CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex);

Memory leak with Delphi/DBExpress

I've a weird problem with my application, its memory usage goes up a few hundred megabytes at once every now and then and eventually the application freezes. The application is written with Delphi, it uses database, COM (for OPC) and TCP/IP.
With FastMM I've got following the screen shot of memory usage. I'm not completely sure how to read that table, but it looks like something has allocated 296463552 bytes (0x100fb000, is that "magic number"?) three times.
Any ideas? Is there any way to track non-Delphi-MM memory allocations?
I'm using Delphi 2007 with FastMM 4.96.
Edit:
I wrote a small helper class using IMallocSpy to track COM memory allocations. Here's excerpt from what I got:
00119023 5:52:27.484 [4496] TCOMAllocSpy.PreRealloc size: 269462304
00119024 5:52:27.734 [4496] (0002760C){ntdll.dll } [7C82860C] KiFastSystemCallRet + $0
00119025 5:52:27.734 [4496] (0009F83A){MyApp.exe} [004A083A] JclDebug.JclCreateThreadStackTrace (Line 3943, "JclDebug.pas" + 7) + $1E
00119026 5:52:27.734 [4496] (003D496A){MyApp.exe} [007D596A] ComLeakHelper.TCOMAllocSpy.DebugStack (Line 46, "ComLeakHelper.pas" + 2) + $9
00119027 5:52:27.734 [4496] (003D4B52){MyApp.exe} [007D5B52] ComLeakHelper.TCOMAllocSpy.PreRealloc (Line 125, "ComLeakHelper.pas" + 4) + $2
00119028 5:52:27.734 [4496] (000053B6){MyApp.exe} [004063B6] System.#WStrAsg (Line 14090, "sys\system.pas" + 10) + $0
00119029 5:52:27.734 [4496] (002E4490){MyApp.exe} [006E5490] DBXCommon.TDBXCommand.SetText (Line 5304, "..\..\..\..\..\src\pas\dbx\driver\DBXCommon.pas" + 13) + $5
00119030 5:52:27.734 [4496] (0010A340){MyApp.exe} [0050B340] WideStrings.TWideStrings.GetValue (Line 580, "common\WideStrings.pas" + 3) + $D
00119031 5:52:27.734 [4496] (002E1AFC){MyApp.exe} [006E2AFC] DBXCommon.TDBXProperties.GetValue (Line 4046, "..\..\..\..\..\src\pas\dbx\driver\DBXCommon.pas" + 1) + $7
00119032 5:52:27.734 [4496] (002E3FC9){MyApp.exe} [006E4FC9] DBXCommon.TDBXConnectionEx.GetProductName (Line 5071, "..\..\..\..\..\src\pas\dbx\driver\DBXCommon.pas" + 1) + $E
00119033 5:52:27.734 [4496] (003765FA){MyApp.exe} [007775FA] SqlExpr.TSQLConnection.DoConnect (Line 2467, "..\..\..\..\..\src\pas\dbx\vcl\SqlExpr.pas" + 66) + $21
00119034 5:52:27.734 [4496] (0011876D){MyApp.exe} [0051976D] DB.TCustomConnection.SetConnected (Line 2628, "DB.pas" + 8) + $4
00119035 5:52:27.734 [4496] (00118728){MyApp.exe} [00519728] DB.TCustomConnection.Open (Line 2611, "DB.pas" + 0) + $4
00119036 5:52:27.734 [4496] (00375D6F){MyApp.exe} [00776D6F] SqlExpr.TSQLConnection.CheckConnection (Line 2302, "..\..\..\..\..\src\pas\dbx\vcl\SqlExpr.pas" + 4) + $2
00119037 5:52:27.734 [4496] (00379241){MyApp.exe} [0077A241] SqlExpr.TCustomSQLDataSet.CheckConnection (Line 3955, "..\..\..\..\..\src\pas\dbx\vcl\SqlExpr.pas" + 2) + $2
00119038 5:52:27.734 [4496] (0037968A){MyApp.exe} [0077A68A] SqlExpr.TCustomSQLDataSet.OpenCursor (Line 4045, "..\..\..\..\..\src\pas\dbx\vcl\SqlExpr.pas" + 3) + $4
00119039 5:52:27.734 [4496] (00125EA9){MyApp.exe} [00526EA9] DB.TDataSet.SetActive (Line 9245, "DB.pas" + 12) + $7
00119040 5:52:27.734 [4496] (00125CA1){MyApp.exe} [00526CA1] DB.TDataSet.Open (Line 9201, "DB.pas" + 1) + $6
...
So, the problem seems to be in database connection. I'm using Firebird 2.1, DBExpress and InterXpress for Firebird drivers from Upscene.
Edit2:
This seems to analyze similar problem, at least the focus is on same lines as here: http://www.yac.com.pl/mt.texts.sqlexpr-2.en.html
The problem is bug in Delphi 2007 DbExpress which surface in multithreaded environment (It's not thread safe, after all). More information here: http://www.yac.com.pl/mt.texts.sqlexpr-2.en.html
When your application is frozen, your can try to look at the stack to discover why it is frozen:
http://code.google.com/p/asmprofiler/wiki/ProcessStackViewer
You can try memproof to trace all resource allocation (and their stacktrace):
http://www.torry.net/tools/debug/memory/memp0948.zip
Try EurekaLog to locate the problem.

how to change desktop wallpaper?

How do I change desktop wallpaper?
I tried this
procedure TForm1.Button1Click(Sender: TObject);
var
PicPath: String;
begin
PicPath := 'C:\test.bmp';
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pChar(PicPath), SPIF_SENDCHANGE)
end;
But it didn't work.
I just tried it with D2007 on XP (and also D2009 on Vista), and this code works.
But to catch If and why it is not working, you should test the result code and get the error from Windows:
if not SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pChar(PicPath), SPIF_SENDCHANGE)then
RaiseLastOSError;
In most cases, it will be because the bmp file is not found:
System Error. Code: 2.
The system cannot find the file specified.
You can check out this python script:
http://gaze.svn.sourceforge.net/viewvc/gaze/trunk/implementation/src/gazelib/os_interface.py?view=markup
This is the python method that does all the magic. It changes a few registry keys and then calls a system method to update the wallpaper.
103 def set_wallpaper(self, file_path) :
104 self.__lock.acquire()
105 # this module is part of python 2.5 by default
106 import ctypes
107 import _winreg
108 reg = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, self.__REGISTRY_PATH, 0, _winreg.KEY_SET_VALUE)
109 # First center the image and turn off tiling
110 _winreg.SetValueEx(reg, "TileWallpaper", 0, _winreg.REG_SZ, "0")
111 _winreg.SetValueEx(reg, "WallpaperStyle", 0, _winreg.REG_SZ, "0")
112 # Set the image
113 _winreg.SetValueEx(reg, "ConvertedWallpaper", 0, _winreg.REG_SZ, os.path.realpath(file_path))
114 _winreg.SetValueEx(reg, "Wallpaper", 0, _winreg.REG_SZ, self.convert_to_bmp(file_path))
115 _winreg.CloseKey(reg)
116 # Notify the changes to the system
117 func_ret_val = ctypes.windll.user32.SystemParametersInfoA(\
118 self.__SPI_SETDESKWALLPAPER,\
119 0,\
120 None,\
121 self.__SPIF_UPDATEINIFILE | self.__SPIF_SENDWININICHANGE)
122 assert func_ret_val == 1
123 self.__lock.release()
Check a VB code here, it can give you a clue.
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imageLocation, SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE)
This should work
Procedure TForm1.Button1Click(Sender: TObject);
var
PicPath : string;
begin
PicPath := 'C:\test.bmp';
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, Pointer(PicPath), SPIF_SENDWININICHANGE);
end;

Resources