Я работаю над запутывания сборки и после запутывания PEVerify выдает следующее сообщение об ошибке:Предупреждает ли PEVerify о дублирующих методах здесь?
[MD]: Error: Method has a duplicate, token=0x060035d8. [token:0x060035D5]
[MD]: Error: Method has a duplicate, token=0x060035d5. [token:0x060035D8]
Вот первый метод декларации с заголовком:
// Token: 0x060035D5 RID: 13781 RVA: 0x000D7828 File Offset: 0x000D5A28
.method private final hidebysig newslot virtual
instance void b() cil managed
{
.override method instance void [mscorlib]System.IDisposable::Dispose()
// Header Size: 12 bytes
// Code Size: 52 (0x34) bytes
// LocalVarSig Token: 0x11000050 RID: 80
.maxstack 2
.locals init (
[0] int32
)
А вот второй один:
// Token: 0x060035D8 RID: 13784 RVA: 0x000248BC File Offset: 0x00022ABC
.method private hidebysig
instance void b() cil managed
{
// Header Size: 1 byte
// Code Size: 31 (0x1F) bytes
.maxstack 8
Похоже на явную реализацию интерфейса IDisposable для меня. Оба метода также называются, поэтому не все вызовы на один были заменены вызовами на другой. Они просто имеют одно и то же имя
Если аналогичный код был написан на C# - компилятор испустил бы методы System.IDisposable.Dispose() и Dispose(), таким образом исключив одинаковые имена и сделав PEVerify тихим.
Для того, чтобы одни и те же имена делают правильный IL, когда один из них явно переопределение метода интерфейса и другой не я написал такие образцы приложение:
namespace ClassLibrary1 {
public interface IX { void M(); }
public class Class1 : IX {
void IX.M() { Console.WriteLine("IX.M()"); }
public void M() { Console.WriteLine("M()"); }
}
public class Class2 {
public static void Main(string[] args) {
var x = new Class1();
x.M();
((IX)x).M();
}
}
}
IL выглядит следующим образом:
// Token: 0x06000002 RID: 2 RVA: 0x00002050 File Offset: 0x00000250
.method private final hidebysig newslot virtual
instance void ClassLibrary1.IX.M() cil managed
{
.override method instance void ClassLibrary1.IX::M()
// Header Size: 1 byte
// Code Size: 13 (0xD) bytes
.maxstack 8
/* 0x00000251 00 */ IL_0000: nop
/* 0x00000252 7201000070 */ IL_0001: ldstr "IX.M()"
/* 0x00000257 280F00000A */ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
/* 0x0000025C 00 */ IL_000B: nop
/* 0x0000025D 2A */ IL_000C: ret
} // end of method Class1::ClassLibrary1.IX.M
// Token: 0x06000003 RID: 3 RVA: 0x0000205E File Offset: 0x0000025E
.method public hidebysig
instance void M() cil managed
{
// Header Size: 1 byte
// Code Size: 13 (0xD) bytes
.maxstack 8
/* 0x0000025F 00 */ IL_0000: nop
/* 0x00000260 720F000070 */ IL_0001: ldstr "M()"
/* 0x00000265 280F00000A */ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
/* 0x0000026A 00 */ IL_000B: nop
/* 0x0000026B 2A */ IL_000C: ret
} // end of method Class1::M
Обратите внимание на разные имена методов.
Тогда я взял в результате ехе и редактируются ClassLibrary1.IX.M
быть просто M
в Class1
(я использовал dnSpy, чтобы сделать это). PEVerify действительно начал выпуск одной и той же проблемы с дублирующими методами, но exe все еще работает с точной печатью M() IX.M()
, как и ожидалось.
Вопрос в том, является ли PEVerify чрезмерным здесь или существует проблема с совпадающими именами, которых я не вижу?
«Оба метода также называются так, поэтому не все вызовы на один были заменены вызовами другого. »- когда вы вызываете не-dispose-overriding, как он узнает, что вы не пытаетесь вызвать отмену распоряжения? Да, вы можете называть его с помощью idisposable, но вы также можете его явно называть (из MSIL. Вы не можете сделать это на C#. Однако вы можете сделать это в VB). – Random832
@ Random832, если я посмотрю на отредактированную сборку ildasm'а - она показывает методы своими жетонами MD, и я предполагаю, что это так, как она сохраняется на в любом случае, сайты вызовов. –
Это в комментариях. Исходный код имеет имя. Проблема заключается в том, что он не может знать, что компилятор действительно выбрал правильный токрен MD, потому что есть два, которые могли быть названы идентичным кодом , – Random832