Reputation: 1580
I have recently upgraded from Delphi 2010 to Delphi 10.2 Tokyo A number of 3rd party libraries have started throwing exceptions in debug mode, and only in debug mode. The most common error is a $C0000005 general protection fault. These are libraries I have been using for years, and well established.
These are 3rd party libs, I do not have access to the source code.
This includes things like jvm.dll and msxml
Any clues? Workarounds? The issues are consistent and persistent, and the apps in question run quite cheerfully when NOT in debug.
In every case I've seen it happen the libraries are dynamically linked rather than statically. I have a suspicion the issue relates to different permissions when in debug mode.
Edit: I traced a DLL call, and it turns out it was trying to write to the DLLs local memory DATA or BSS. In Delphi 2010 it allows this quite cheerfully. In Tokyo it throws the $C0000005 error. I'm assuming this is a bug or setup issue with the latest Delphi debugger.
Edit 2: I have managed to pull out a minimal app to reproduce the issue. https://www.dropbox.com/s/uy8e9rw0qjxspie/testdll.zip?dl=0 The download contains a minimal 32 bit executable (testdll). It is statically linked to a 3rd party dll mirixafind.dll. It is an old dll and I don't have access to the source. If you run testdll standalone or without debugging, hitting the 'Mirixa' button prints some lines to the screen and stops. If you run WITH debugging it will fall over with a $C0000005 error, attempting to write a string to a section of memory that appears to be part of the dll's DATA (or possible BSS) segment. A colleague has duplicated it on a separate installation. It does not happen in Delphi 2010.
Edit 3: Stack trace:
:757db78d user32.GetWindowTextA + 0x1d
:0068fbbf ; C:\Users\Robbie\Documents\Embarcadero\Studio\Projects\Win32\Debug\mirixafind.dll
:757e9275 ; C:\WINDOWS\SysWOW64\user32.dll
:757e757a user32.EnumWindows + 0x1a
:0068fca5 ; C:\Users\Robbie\Documents\Embarcadero\Studio\Projects\Win32\Debug\mirixafind.dll
:00691afa ; C:\Users\Robbie\Documents\Embarcadero\Studio\Projects\Win32\Debug\mirixafind.dll
:00690bcd ; C:\Users\Robbie\Documents\Embarcadero\Studio\Projects\Win32\Debug\mirixafind.dll
testdll1.TForm1.Button2Click($234B380)
Vcl.Controls.TControl.Click
Vcl.StdCtrls.TCustomButton.Click
Vcl.StdCtrls.TCustomButton.CNCommand(???)
Vcl.Controls.TControl.WndProc((48401, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.Controls.TWinControl.WndProc((48401, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.StdCtrls.TButtonControl.WndProc((48401, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.Controls.TControl.Perform(???,???,1117908)
Vcl.Controls.DoControlMsg(???,(no value))
Vcl.Controls.TWinControl.WMCommand((273, (), 3796, 0, (), 1117908, 0))
Vcl.Controls.TControl.WndProc((273, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.Controls.TWinControl.WndProc((273, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.Controls.TWinControl.MainWndProc(???)
System.Classes.StdWndProc(1575384,273,3796,1117908)
:757ed2b3 user32.SetManipulationInputTarget + 0x53
:757ce88a ; C:\WINDOWS\SysWOW64\user32.dll
:757f764b ; C:\WINDOWS\SysWOW64\user32.dll
:757d0c00 ; C:\WINDOWS\SysWOW64\user32.dll
:6ccdd36f ; C:\WINDOWS\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.14393.953_none_89c2555adb023171\comctl32.dll
:6cced065 ; C:\WINDOWS\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.14393.953_none_89c2555adb023171\comctl32.dll
:757ed2b3 user32.SetManipulationInputTarget + 0x53
:757ce88a ; C:\WINDOWS\SysWOW64\user32.dll
:757cdf17 user32.CallWindowProcW + 0x97
Vcl.Controls.TWinControl.DefaultHandler(???)
:00521b5b TWinControl.DefaultHandler + $EB
:00521a4a TWinControl.WndProc + $5EE
:00536559 TButtonControl.WndProc + $71
:004c2b5a StdWndProc + $16
:757ed2b3 user32.SetManipulationInputTarget + 0x53
:757ce88a ; C:\WINDOWS\SysWOW64\user32.dll
:757ce1e4 ; C:\WINDOWS\SysWOW64\user32.dll
:757cdfa0 user32.DispatchMessageW + 0x10
First chance exception at $757DB78D. Exception class $C0000005 with message 'access violation at 0x757db78d: write of address 0x00974409'. Process testdll.exe (26036)
Module Load: MirixaFind.dll. No Debug Info. Base Address: $00970000. Process testdll.exe (26036)
Tdump of dll gives the following info:
Object table:
# Name VirtSize RVA PhysSize Phys off Flags
-- -------- -------- -------- -------- -------- --------
01 CODE 00052714 00001000 00052800 00000400 60000020 [CER]
02 DATA 000013D8 00054000 00001400 00052C00 C0000040 [IRW]
03 BSS 00000B7D 00056000 00000000 00054000 C0000000 [RW]
04 .idata 00001F86 00057000 00002000 00054000 C0000040 [IRW]
05 .edata 0000139F 00059000 00001400 00056000 50000040 [IRS]
06 .reloc 0000588C 0005B000 00005A00 00057400 50000040 [IRS]
07 .rsrc 00004800 00061000 00004800 0005CE00 50000040 [IRS]
Key to section flags:
C - contains code
E - executable
I - contains initialized data
R - readable
S - shareable
W - writeable
As far as I can tell, in this case 0x00974409 should be an entirely legitimate address.
Upvotes: 2
Views: 2167
Reputation: 1580
As it turns out, what I was seeing was the debugger catching an exception that was being handled in the dll.
Tools-->Options-->Debugger Optionss-->Embarcadero Debuggers-->Native OS Exceptions-->32-bit windows OS Exceptions-->Access Violation ($C0000005) was set to "Handled by Debugger"
In prior versions of Delphi this defaulted to "User Program" (as did all the other Native OS Exceptions)
It looked worse than it was, because it was occurring in the middle of a loop, so it kept being thrown continuously... but if I'd just told Delphi to ignore the exception it would have gone away. (Headdesk)
Upvotes: 3
Reputation: 11919
Posting as an answer so the code is formatted correctly.
So, from the stack trace it looks like the code is enumerating all the windows to get the window text (possibly the title of each window?). It's hard to fathom out, but if you could dump the assembly at 0x0068fbbf you will see the parameters being passed to GetWindowText. The prototype (below) is fairly hard to get wrong.
int WINAPI GetWindowText(_In_ HWND hWnd, _Out_ LPTSTR lpString, _In_ int nMaxCount);
My guess would be lpString
is null.
Just read the documentation on GetWindowText:
Copies the text of the specified window's title bar (if it has one) into a buffer. If the specified window is a control, the text of the control is copied. However, GetWindowText cannot retrieve the text of a control in another application.
I wonder if you are trying to enumerate Windows on an application this isn't yours?
Upvotes: 0
Reputation: 11919
Error 5 is access denied.
This could either be an attempt to write to null (or anywhere within the first 64k of data), or (as you surmise) it's calling a Win32 API function that it doesn't have the correct security settings.
I presume you have tried running your app under an administrator account, to see if it is related to that?
Upvotes: 0