[Mono-bugs] [Bug 542959] New: Incorrect IL generated when creating a delegate
bugzilla_noreply at novell.com
bugzilla_noreply at novell.com
Tue Sep 29 15:34:40 EDT 2009
http://bugzilla.novell.com/show_bug.cgi?id=542959
Summary: Incorrect IL generated when creating a delegate
Classification: Mono
Product: Mono: Compilers
Version: SVN
Platform: x86-64
OS/Version: All
Status: NEW
Severity: Normal
Priority: P5 - None
Component: C#
AssignedTo: mono-bugs at lists.ximian.com
ReportedBy: jpryor at novell.com
QAContact: mono-bugs at lists.ximian.com
Found By: ---
User-Agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US)
AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.202.2 Safari/532.0
Summary is likely wrong; not sure how best to summarize this.
Consider the following code:
using System;
using System.Collections;
using System.Collections.Generic;
namespace MyAddressBook {
public struct ABMultiValueEntry<T>
{
ABMultiValue<T> self;
int index;
internal ABMultiValueEntry (ABMultiValue<T> self, int index)
{
this.self = self;
this.index = index;
}
public T Value {
get {
var v = IntPtr.Zero;
Console.Error.WriteLine("# ABMultiValueEntry.Value; v={0}", v);
return self.toManaged (v);
}
}
}
public class ABMultiValue<T>
{
protected List<KeyValuePair<T, string>> items = new List<KeyValuePair<T,
string>>();
internal Converter<IntPtr, T> toManaged;
internal ABMultiValue (Converter<IntPtr, T> toManaged)
{
if (toManaged == null)
throw new ArgumentNullException ("toManaged");
this.toManaged = toManaged;
}
public ABMultiValueEntry<T> this [int index] {
get {
if (index < 0 || index >= items.Count)
throw new IndexOutOfRangeException ();
return new ABMultiValueEntry<T> (this, index);
}
}
public void Add (T value, string label)
{
items.Add(new KeyValuePair<T, string>(value, label));
}
}
public class ABPerson {
internal static string ToString (IntPtr value)
{
Console.Error.WriteLine("# ABPerson.ToString(IntPtr): value={0}",
value);
if (value == IntPtr.Zero)
return null;
return value.ToString ();
}
public ABMultiValue<string> GetPhones ()
{
var p = new ABMultiValue<string> (ToString);
p.Add ("value1", "label1");
return p;
}
}
class Demo {
static void Main (string [] args)
{
var phoneNumbers = new ABPerson().GetPhones();
var entry = phoneNumbers[0];
Console.Error.WriteLine("# entry.Value={0}", entry.Value);
}
}
}
It's simple: ABPerson.GetPhones() returns an ABMultiValueEntry<string>,
providing the ABMultiValueEntry<string> a Converter<IntPtr, string> delegate
which refers to the static ABPerson.ToString(IntPtr) method.
We then call phoneNumbers[0].Value, which invokes the Converter<IntPtr, string>
delegate to obtain an actual value.
The problem: the IntPtr value is CORRUPTED during the invocation!
Program output:
# ABMultiValueEntry.Value; v=0
# ABPerson.ToString(IntPtr): value=140373527179248
# entry.Value=140373527179248
Expected output: value should always be 0, not some random garbage value.
Here's why I think it's an "incorrect" IL issue. Take the IL of the above app:
monodis tostring.exe > tostring.il
Then modify ABPerson.GetPhones() so that it uses ldnull instead of ldarg.0,
i.e. change line 206 from:
IL_0000: ldarg.0
to:
IL_0000: ldnull
Recompile:
ilasm /exe /out:tostring.new.exe tostring.il
Run:
$ mono tostring.new.exe
# ABMultiValueEntry.Value; v=0
# ABPerson.ToString(IntPtr): value=0
# entry.Value=
The SAME effect can be had by renaming ABPerson.ToString(IntPtr) to
ABPerson._ToString(IntPtr). So apparently the problem is using the name
"ToString".
Reproducible: Always
Steps to Reproduce:
1.
2.
3.
--
Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.
More information about the mono-bugs
mailing list