8

I have a random Runtime Error 216 that appears on application close.

I have debugged as far as I can and the error is thrown in SysUtils.FinalizeUnits.

I have gone over the code and ensure all created objects are freed.

The number on the runtime error, 0040054A, is not present in the mapfile. Do you know what this means?

Can anyone tell me how to find out what is throwing the error?

Jackie
  • 103
  • 1
  • 1
  • 4

7 Answers7

8

This is VERY OLD Delphi problem - wrong exception handling in unit initialization/finalization process.

The problem easy to reproduce - just make any program error/exception (division by zero for instance) in initialization block of any unit. The exception will be created correctly. But then, before the exception rise, the unit finalization process destroy the exception object. And thus, when the exception object accessed, the "runtime error 216" occured.

Vasily Ivanov
  • 81
  • 1
  • 2
  • 1
    Thanks a lot for this comment! Using your info I debugged my unit initialization unit by unit, found a unit initialization with an exception on it (only it didn't rise to the debugger) and could fix the problem. – Ludecan Dec 06 '17 at 00:19
6

I'd suspect a memory leak (all Runtime Errors 216 I've encountered so far were) and use a profiler (visual inspection is never as good as a tool). Since you're using Delphi XE, you should give AQTime a try (it's included), see also

Delphi - Check if memory is being released "on time"

Kind regards, Frank

Community
  • 1
  • 1
Frank Schmitt
  • 27,865
  • 9
  • 65
  • 100
  • 2
    Thanks, I used AQTime as suggested by Frank - it worked well and helped me track down one pesky object not freed correctly. – Jackie Mar 17 '11 at 21:32
5

Since runtime error 216 is an access violation, this may indicate that you're attempting to use something that you've already freed.

Addresses in the map file are based at 0, but that's not where your EXE file gets loaded into memory. Your EXE gets loaded at its preferred base address, which is usually $400000. Subtract that from the address you have. The address you're looking for in the map file is $0000054a.

David Heffernan
  • 572,264
  • 40
  • 974
  • 1,389
Rob Kennedy
  • 156,531
  • 20
  • 258
  • 446
  • 1
    Actually you subtract $401000. I'm not sure where this code can live though! I guess it's some code that the linker brings in take get from WinMain to the beginning of the .dpr file and back again at the end. – David Heffernan Mar 17 '11 at 08:05
  • Thanks, unfortunately $0000054A is not in the mapfile either. The linking 'base address' is 00400000. What am I missing here? – Jackie Mar 17 '11 at 08:14
3

There was a similar question, Read: How to debug a crash that only occurs on application shutdown? (Delphi)

Consider using Memory profiler, this may help identifying live objects after app was terminitated.

Community
  • 1
  • 1
CloudyMarble
  • 34,949
  • 69
  • 92
  • 126
  • Thanks, had read this and got as far as I can based on much of the excellent information in that article. – Jackie Mar 17 '11 at 07:47
  • 1
    @user663825: i can recommend you using an Allocation profiler if nothing else helps, it doesnt ensure success but it may help, personally iv used the AQ-Time from Smartbear (http://smartbear.com/support/viewarticle/18254/?=%22aid%22) which shows how many objects of which type are not freed at the end of your application, but its not free, anyway there are some freeware delphi Memory profiler if you intend to do that. – CloudyMarble Mar 17 '11 at 08:05
  • 1
    Thanks, I used AQTime included in Delphi XE - it worked well and helped me track down one pesky object not freed correctly. – Jackie Mar 17 '11 at 21:31
3

I suggest you try the FastMM Full Debug Mode, and either statically link that into your app, or use it as a package (if your app uses packages).

Warren P
  • 58,696
  • 38
  • 168
  • 301
  • Thanks, I used AQTime as suggested by Frank - it worked well and helped me track down one pesky object not freed correctly. – Jackie Mar 17 '11 at 21:30
  • AQTime rules. On versions where it's not included "out of the box", it's expensive, but when it finds a bug for you, it's worth it. And even on XE editions and higher, where it's included, the full version is far more powerful than the "lite" version. If only the licensing restrictions on the full version weren't so crappy. – Warren P Oct 29 '12 at 20:34
0

You can use the method I used to fix mine.

I commented out the main program, and added code back until it failed.

Turns out that it did not want me to call couninitialize at all. Did not throw an error at the time, but failed after program termination with a 216. Removing the offending statement fixed it.

Since this was maybe 6 statements before end. statement, I don't imagine it will matter.

This method is easy if you are consistent about using // for comments. I moved IO statements that needed curly brackets to a procedure.

-2

On Microsoft's oficial web site it is mentioned that, this issue can occur if your computer is infected with a SubSeven Trojan virus.

Antivirus software and windows registry cleaner should help.

Jiemurat
  • 1,499
  • 19
  • 18