📜 ⬆️ ⬇️

Release Version: debugging is just beginning ...

What is it about?


Your program has finally earned, the customer confidently pokes buttons on the test site, everything is working properly ... but do not be in a hurry to rejoice: problems may lie in wait for you after the release version. The software begins to roll with obscure bugs, the customer is ready to tear you to the British flag ...

Do you think this is a problem only Si-Schnick? You're wrong!

Practical example


Usually you are accustomed to the fact that you lay out a debug version on the test site (this, of course, does not apply to everyone, but believe me, this happens very often). This saves time, and more debugging information, you can hook on remote debugging ...

It would seem that the burden of releasing the release does not concern you very much, yet .NET is a little bit improved C ++ in which there are certain problems . But everything is not as cloudless as it may seem at first.
')
So, an example:
static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  1. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  2. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  3. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  4. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  5. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  6. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  7. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  8. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
  9. static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .
static void Main( string [] args) { System.Threading.Timer t = new System.Threading.Timer(state => { Console .WriteLine( "Timer!" ); GC.Collect(); }, null , 0, 1000); Console .ReadKey(); } * This source code was highlighted with Source Code Highlighter .


The simplest code, which according to the author’s idea is to write the coveted “Timer!” To the console once a second. Debugging in the project compiled in the debug configuration does not reveal anything suspicious, and a release is being prepared ... in which the program does not work .

Debriefing


Yes, yes, this “bug” is a direct consequence of optimization (and, of course, a small negligence of the programmer). Negligence lies in the fact that the specified System.Threading.Timer actually inherits IDisposable, and, for good, we should call the Dispose () method for it. Well, suppose we do not do this (in fact, this is irrelevant).

We study the listing of IL code generated in the release and debug versions and see this.
debug:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 5
.locals init (
[0] class [mscorlib]System.Threading.Timer t)

L_0000: nop
L_0001: ldsfld class
[mscorlib]System.Threading.TimerCallback ConsoleApplication11.Program::CS$<>9__CachedAnonymousMethodDelegate1
....



and release:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 8
L_0000: ldsfld class [mscorlib]System.Threading.TimerCallback ConsoleApplication11.Program::CS$<>9__CachedAnonymousMethodDelegate1
....



I highlighted the difference.

For those who have not figured it out yet

In the debug version, the compiler leaves the Timer link on the stack not used anywhere (except for the declaration), and the GC sees that the link is alive (until the method is finished) does nothing. The timer is working.

In the release of the same version, the link does not exist anywhere, and the first (not guaranteed) method GC.Collect () will destroy the timer.

Afterword


I sincerely hope that you will never have to fall for obvious (or not) optimizer bugs, as in the example above, in real life. The search for such bugs (especially on the customer side) is very complicated and I can only recommend assembling the debug version of all components and gradually compiling the parts in the release in order to find the “defective” assembly and its further analysis. Distributing debug information (.pdb file usually) can also help.

Good Friday, keep logs 8-)

Source: https://habr.com/ru/post/108815/


All Articles