Lars Fosdal 1775 Posted March 20, 2019 Does anyone recognize that seemingly hardcoded address? The call stack indicates that it happens in Rio 10.3.1 source - but searching the source does not yield anything. Can it be Eurekalog that tries to tell me something about referencing a deleted or inaccessible piece of memory? #BAD: EAccessViolation: Access violation at address 0040CEEC in module 'MyApp.exe'. Read of address DEADBEE7. DBServer\INDUSTRIELL\DBName # 3017235 20.03.2019 13:23:06 (Brukerinterface, CRITICAL) MyApp_ClientId @ [0040CEEC] System._UStrAsg __________ CallStack [0040CEEC] System._UStrAsg [01561AF4] System.Generics.Collections.pas.{GridSet}TGridSet.TFieldValue<System.string>.SetValue (Line 4745, "System.Generics.Collections.pas") [0156241F] System.Generics.Collections.pas.{GridSet}TGridSet.TFieldValue<System.string>.CopyRow (Line 4745, "System.Generics.Collections.pas") [01558452] GridSet.TGridSet.CopyRow (Line 1002, "GridSet.pas") [01B92885] frmPSDExpeditionDeliveries2.TDeliverySet.UpdateFromDeliverySet (Line 4108, "frmPSDExpeditionDeliveries2.pas") [01B8F919] frmPSDExpeditionDeliveries2.TDeliveryGrid.RefreshByRouteList (Line 3671, "frmPSDExpeditionDeliveries2.pas") Share this post Link to post
Lars Fosdal 1775 Posted March 20, 2019 Also spotted: Read of address DEADC00B. Normally I'd expect to see things like this EUseAfterFreeError: Application made attempt to call method of already deleted object: $071EC5A0 OBJECT [TMyClass] 404 bytes. Share this post Link to post
GPRSNerd 11 Posted March 20, 2019 (edited) Programmers jokes, there exist a couple of these "HEX speak" or "magic number" addresses: DEADC0DE, DEADBEEF... https://en.wikipedia.org/wiki/Hexspeak I use them as constraints in unittesting to check that a peer or protocol is using the expected values. So the programmer wants to tell you something... Edited March 20, 2019 by GPRSNerd Share this post Link to post
Lars Fosdal 1775 Posted March 20, 2019 The question is: Which programmer? What raises the AV? Share this post Link to post
Микола Петрівський 10 Posted March 20, 2019 In such situation I usually try other debugging tools and compare results. In my list I have FastMM4 in FullDebugMode and SafeMM: https://stackoverflow.com/questions/1039646/trying-to-locate-safemm-for-delphi The last one is especially useful when you want to see precise line of code with the bug. If nothing helps, then I read this article: https://www.eurekalog.com/help/eurekalog/eaccessviolation.php And especially list of mistakes that can cause AV. Usually it is one of them. Share this post Link to post
Remy Lebeau 1345 Posted March 20, 2019 (edited) 2 hours ago, Lars Fosdal said: BAD: EAccessViolation: Access violation at address 0040CEEC in module 'MyApp.exe'. Read of address DEADBEE7. DBServer\INDUSTRIELL\DBName # 3017235 20.03.2019 13:23:06 (Brukerinterface, CRITICAL) MyApp_ClientId @ [0040CEEC] System._UStrAsg In some piece of code somewhere, a pointer was set to $DEADBEEF, most likely after the object it was pointing to had been freed, and then that same pointer was used afterwards by code running at address $0040CEEC trying to access a data member at offset -8 ($DEADBEE7) via that pointer. Magic addresses like $DEADBEEF are commonly used for debugging such mistakes. In this case, the code at address $0040CEEC is the System._UStrAsg() function, which is used to assign a UnicodeString to another UnicodeString. Offset -8 is the StrRec.refCount field in the UnicodeString data header, which makes sense as UStrAsg() does increment that field. In other words, some piece of code tried to assign a UnicodeString value to a dead UnicodeString variable. UStrAsg() was called by TFieldValue.SetValue(), so SetValue() was likely called on an invalid TFieldValue object inside of TGridSet.CopyRow(), which was called by TDeliverySet.UpdateFromDeliverySet() inside of TDeliveryGrid.RefreshByRouteList(). So, start in RefreshByRouteList() and work your way into UpdateFromDeliverySet() and try to figure out how it may be accessing an invalid TFieldValue object. 1 hour ago, Lars Fosdal said: What raises the AV? The Operation System, when the invalid memory address $DEADBEE7 is accessed. Delphi's RTL catches that error from the OS, creates an EAccessViolation object for it, and then raises it. Edited March 20, 2019 by Remy Lebeau 3 1 Share this post Link to post
Микола Петрівський 10 Posted March 20, 2019 2 hours ago, Lars Fosdal said: Also spotted: Read of address DEADC00B. Normally I'd expect to see things like this EUseAfterFreeError: Application made attempt to call method of already deleted object: $071EC5A0 OBJECT [TMyClass] 404 bytes. It is not so easy to detect, that current AV really is a usage of freed object. Especially if you have multiple DLLs, compiled in different versions of Delphi, or something like that. SafeMM can shed some light even in such situation, but at a cost of big memory leak. Share this post Link to post
Lars Fosdal 1775 Posted March 21, 2019 17 hours ago, Remy Lebeau said: In some piece of code somewhere, a pointer was set to $DEADBEEF, most likely after the object it was pointing to had been freed, and then that same pointer was used afterwards by code running at address $0040CEEC trying to access a data member at offset -8 ($DEADBEE7) via that pointer. Magic addresses like $DEADBEEF are commonly used for debugging such mistakes. [deletia] 1 Excellent analysis, Remy. As I often do, I did not ask the right question - which should have been: What sets dead memory references to $DEADxxxx? RTL? EurekaLog? OS? Share this post Link to post
Hallvard Vassbotn 3 Posted March 21, 2019 Typically debug-enabled version of memory manager. On Phone now, so can’t check, but I think FastMM4 uses a different pattern (all $80, IIRC) 1 Share this post Link to post
Stefan Glienke 1978 Posted March 21, 2019 (edited) 6 minutes ago, Hallvard Vassbotn said: I think FastMM4 uses a different pattern (all $80, IIRC) Correct - it seems to be EurekaLog (see point 3. "When memory is released": https://www.eurekalog.com/help/eurekalog/index.php?memory_leaks_page.php) I would say its that a destroyed TFieldValue was not removed from the list inside the TGridSet - so locate where those are destroyed and check if they are properly removed from that list when in it. Edited March 21, 2019 by Stefan Glienke 2 Share this post Link to post