Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mono - Debug.Assert does not work

Tags:

c#

mono

I have this program here:

namespace TodoPlus {
    using System.Diagnostics;

    public class LameProg {

        public LameProg() {}

        public static void Main(string[] args) {
            int a = 2;
            int b = 3;
            Debug.Assert(a == b, "Bleh");
            System.Console.WriteLine("Haha, it didn't work");
        }
    }
}

And somehow, Debug.Assert is not working.

I am using Mono 2.10.5 and this is what I use to compile and execute:

dmcs LameProg.cs

mono ./LameProg.exe

How can I make this work? I wish it to have the same effect as the assert macro in C, which is to say it should just downright crash the program. Is it possible to do this with Debug.Assert or is there some other function that achieves this?

like image 677
yanhan Avatar asked Sep 20 '11 03:09

yanhan


3 Answers

There's another trick: you can add "exit now" behavior through a TraceListener, because Debug.Assert failures trigger a call to Fail() in the trace listener.

You still need to -define:DEBUG (and TRACE?). I personally expect Assert() calls (in DEBUG builds) to stop my program, dump debug info and exit. So, this is how I do it:

In my code I install a custom trace listener to dump stack and add a call to Exit(). And viola! You have an industry standard response to Assert.Fail(). You could also, for example, print timestamps here, etc.

public class DumpStackTraceListener : TraceListener
{
  public override void Write( string message )
  {
     Console.Write( message );
  }

  public override void WriteLine(string message)
  {
     Console.WriteLine( message );
  }

  public override void Fail(string message)
  {
     Fail( message, String.Empty );
  }

  public override void Fail(string message1, string message2)
  {
     if (null == message2)
        message2 = String.Empty;

     Console.WriteLine( "{0}: {1}", message1, message2 );
     Console.WriteLine( "Stack Trace:" );

     StackTrace trace = new StackTrace( true );
     foreach (StackFrame frame in trace.GetFrames())
     {
        MethodBase frameClass = frame.GetMethod();
        Console.WriteLine( "  {2}.{3} {0}:{1}", 
                           frame.GetFileName(),
                           frame.GetFileLineNumber(),
                           frameClass.DeclaringType,
                           frameClass.Name );
     }

#if DEBUG
     Console.WriteLine( "Exiting because Fail" );
     Environment.Exit( 1 );
#endif
  }
}

Combine with a call to:

#if DEBUG
   Debug.Listeners.Add( new DumpStackTraceListener() );
#endif

And you're good to go.

like image 180
tekHedd Avatar answered Oct 22 '22 13:10

tekHedd


  1. Debug.Assert is annotated with [ConditionalAttribute("DEBUG")]. This means that all invocations are removed by the compiler unless the DEBUG preprocessor symbol is defined. Try this:

    $ dmcs -d:DEBUG LameProg.cs
    
  2. Mono does not show a dialog box like Microsoft's .NET implementation when an assertion is hit. You need to set a TraceListener, e.g.

    $ export MONO_TRACE_LISTENER=Console.Error
    $ mono LameProg.exe
    

Debug.Assert invocations are typically used in debug builds and removed from release builds. If you want to make sure that a certain condition holds, and this check should be present in release builds, use an if statement and throw an exception:

public static void Main(string[] args)
{
    int a = 2;
    int b = 3;
    if (a != b)
    {
        throw new Exception("Bleh");
    }
    System.Console.WriteLine("Haha it didn't work");
}
like image 22
dtb Avatar answered Oct 22 '22 12:10

dtb


I believe you need two things: the DEBUG attribute to the compiler, and a 'trace listener' for the runtime. I got it to work with

% export MONO_TRACE_LISTENER=Console.Error
% mcs -define:DEBUG -debug Prog.cs
% mono Prog.exe

That still doesn't exit immediately on assertion failure as I would have expected, but at least it prints something.

like image 45
Ed Avis Avatar answered Oct 22 '22 13:10

Ed Avis