Strange behavior with dynamic code compilation and VS.NET debuggin


G

Guest

When I run the following code I would suspect a null reference exception to
be thrown:

param1 = null;
int x = param1.Length;

However, when I compile this code dynamically into a class and method a null
reference exception is ONLY thrown if the debugger is attached???? Otherwise
no exception is thrown. Can someone please explain this? I included the
code below - create a console application and overwrite the existing class
with the code below.

CODE TO REPRODUCE:

using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Assembly a = CreateAssembly();
object o = a.CreateInstance("ConsoleApplication1.TestClass");
MethodInfo info = o.GetType().GetMethod("RunMe");
info.Invoke(o, new object[] { null });
}

private static Assembly CreateAssembly()
{
string src = @"
namespace ConsoleApplication1
{
using System;

public class TestClass
{
public virtual void RunMe(string param1)
{
int x = param1.Length;
}
}
}";

CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters compilerParameters = new CompilerParameters();
compilerParameters.GenerateInMemory = true;
compilerParameters.IncludeDebugInformation = false;
compilerParameters.GenerateExecutable = false;

CompilerResults results =
provider.CompileAssemblyFromSource(compilerParameters,
src);

return results.CompiledAssembly;
}
}
}
 
Ad

Advertisements

J

Jon Skeet [C# MVP]

Mike Miller said:
When I run the following code I would suspect a null reference exception to
be thrown:

param1 = null;
int x = param1.Length;

However, when I compile this code dynamically into a class and method a null
reference exception is ONLY thrown if the debugger is attached???? Otherwise
no exception is thrown. Can someone please explain this? I included the
code below - create a console application and overwrite the existing class
with the code below.

<snip>

Interesting. It looks like optimization is deciding that as you don't
use the value of x, it shouldn't bother calculating it. Definitely
looks like a bug to me.
 
G

Guest

Try changing the following line (change "false" to "true"):

compilerParameters.IncludeDebugInformation = true;

And you'll get the usual exception information when the program aborts.
Regards,
RHS
 
G

Guest

So the behavior is suppose to be different??? This doesn't make any sense -
so when I compile with debugging information I get different behavior then
when I compile without it? Isn't optimization a change in performance, not
behavior? Thanks for the response, I guess what I am getting at is how does
one troubleshoot optimized code if when you debug it the problem disappears?
Maybe we should go back to using lots of write lines instead of the debugger
;)


Richard Hale Shaw (C# MVP) said:
Try changing the following line (change "false" to "true"):

compilerParameters.IncludeDebugInformation = true;

And you'll get the usual exception information when the program aborts.
Regards,
RHS


Mike Miller said:
When I run the following code I would suspect a null reference exception to
be thrown:

param1 = null;
int x = param1.Length;

However, when I compile this code dynamically into a class and method a null
reference exception is ONLY thrown if the debugger is attached???? Otherwise
no exception is thrown. Can someone please explain this? I included the
code below - create a console application and overwrite the existing class
with the code below.

CODE TO REPRODUCE:

using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Assembly a = CreateAssembly();
object o = a.CreateInstance("ConsoleApplication1.TestClass");
MethodInfo info = o.GetType().GetMethod("RunMe");
info.Invoke(o, new object[] { null });
}

private static Assembly CreateAssembly()
{
string src = @"
namespace ConsoleApplication1
{
using System;

public class TestClass
{
public virtual void RunMe(string param1)
{
int x = param1.Length;
}
}
}";

CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters compilerParameters = new CompilerParameters();
compilerParameters.GenerateInMemory = true;
compilerParameters.IncludeDebugInformation = false;
compilerParameters.GenerateExecutable = false;

CompilerResults results =
provider.CompileAssemblyFromSource(compilerParameters,
src);

return results.CompiledAssembly;
}
}
}
 
G

Guest

Mike,
Sorry to have been terse before. Ben Day suggested I take a look at this for
you.

I think someone else suggested that it was optimization related; I noticed
that the you'd turned off debugging in the generated assembly and noticed
that the results changed considerably.

Wanted to make you at least aware of that, since it did generate all the
exception information that way.

BTW--I find it easier to debug CodeDom related problems by having the
assembly written to disk and then executing it, so you can run it standalone
if appropriate.

Hope this helps.
Regards,
RHS

Mike Miller said:
So the behavior is suppose to be different??? This doesn't make any sense -
so when I compile with debugging information I get different behavior then
when I compile without it? Isn't optimization a change in performance, not
behavior? Thanks for the response, I guess what I am getting at is how does
one troubleshoot optimized code if when you debug it the problem disappears?
Maybe we should go back to using lots of write lines instead of the debugger
;)


Richard Hale Shaw (C# MVP) said:
Try changing the following line (change "false" to "true"):

compilerParameters.IncludeDebugInformation = true;

And you'll get the usual exception information when the program aborts.
Regards,
RHS


Mike Miller said:
When I run the following code I would suspect a null reference exception to
be thrown:

param1 = null;
int x = param1.Length;

However, when I compile this code dynamically into a class and method a null
reference exception is ONLY thrown if the debugger is attached???? Otherwise
no exception is thrown. Can someone please explain this? I included the
code below - create a console application and overwrite the existing class
with the code below.

CODE TO REPRODUCE:

using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Assembly a = CreateAssembly();
object o = a.CreateInstance("ConsoleApplication1.TestClass");
MethodInfo info = o.GetType().GetMethod("RunMe");
info.Invoke(o, new object[] { null });
}

private static Assembly CreateAssembly()
{
string src = @"
namespace ConsoleApplication1
{
using System;

public class TestClass
{
public virtual void RunMe(string param1)
{
int x = param1.Length;
}
}
}";

CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters compilerParameters = new CompilerParameters();
compilerParameters.GenerateInMemory = true;
compilerParameters.IncludeDebugInformation = false;
compilerParameters.GenerateExecutable = false;

CompilerResults results =
provider.CompileAssemblyFromSource(compilerParameters,
src);

return results.CompiledAssembly;
}
}
}
 
Ad

Advertisements

G

Guest

I appreciate you taking the time to answer and thanks for the information -
it was helpful at least for hacking around the problem.

Richard Hale Shaw (C# MVP) said:
Mike,
Sorry to have been terse before. Ben Day suggested I take a look at this for
you.

I think someone else suggested that it was optimization related; I noticed
that the you'd turned off debugging in the generated assembly and noticed
that the results changed considerably.

Wanted to make you at least aware of that, since it did generate all the
exception information that way.

BTW--I find it easier to debug CodeDom related problems by having the
assembly written to disk and then executing it, so you can run it standalone
if appropriate.

Hope this helps.
Regards,
RHS

Mike Miller said:
So the behavior is suppose to be different??? This doesn't make any sense -
so when I compile with debugging information I get different behavior then
when I compile without it? Isn't optimization a change in performance, not
behavior? Thanks for the response, I guess what I am getting at is how does
one troubleshoot optimized code if when you debug it the problem disappears?
Maybe we should go back to using lots of write lines instead of the debugger
;)


Richard Hale Shaw (C# MVP) said:
Try changing the following line (change "false" to "true"):

compilerParameters.IncludeDebugInformation = true;

And you'll get the usual exception information when the program aborts.
Regards,
RHS


:

When I run the following code I would suspect a null reference exception to
be thrown:

param1 = null;
int x = param1.Length;

However, when I compile this code dynamically into a class and method a null
reference exception is ONLY thrown if the debugger is attached???? Otherwise
no exception is thrown. Can someone please explain this? I included the
code below - create a console application and overwrite the existing class
with the code below.

CODE TO REPRODUCE:

using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Assembly a = CreateAssembly();
object o = a.CreateInstance("ConsoleApplication1.TestClass");
MethodInfo info = o.GetType().GetMethod("RunMe");
info.Invoke(o, new object[] { null });
}

private static Assembly CreateAssembly()
{
string src = @"
namespace ConsoleApplication1
{
using System;

public class TestClass
{
public virtual void RunMe(string param1)
{
int x = param1.Length;
}
}
}";

CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters compilerParameters = new CompilerParameters();
compilerParameters.GenerateInMemory = true;
compilerParameters.IncludeDebugInformation = false;
compilerParameters.GenerateExecutable = false;

CompilerResults results =
provider.CompileAssemblyFromSource(compilerParameters,
src);

return results.CompiledAssembly;
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top