Вызов метода экземпляра для нулевой ссылки в IL

Правильно ли, что метод экземпляра может быть вызван по нулевой ссылке в IL ..? Есть ли пример, чтобы показать это ..?

6
задан Dirk Vollmar 10 August 2010 в 10:42
поделиться

3 ответа

Да, это возможно, если метод не использует this , потому что CLR не выполняет нулевую проверку для инструкций call .

Вам придется изменить IL вручную, поскольку компилятор C # почти всегда генерирует инструкцию callvirt 1 .

См. Подробности и пример в этом сообщении в блоге:

Методы экземпляра, вызываемые по нулевым ссылкам

Пример

.method private hidebysig static void  Main(string[] args) cil managed
{
    .entrypoint
    // Code size       18 (0x12)
    .maxstack  1
    .locals init ([0] class SomeClass o, [1] string hello)
    IL_0000:  nop
    IL_0001:  ldnull
    IL_0002:  stloc.0
    IL_0003:  ldloc.0
    IL_0004:  call       instance string SomeClass::GetHello()
    IL_0009:  stloc.1
    IL_000a:  ldloc.1
    IL_000b:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0010:  nop
    IL_0011:  ret
} 

1 Фактически причина того, что компилятор C # выдает callvirt даже в случаях, когда простой инструкции call будет достаточно, чтобы предотвратить вызов методов экземпляра для пустых ссылок. При таком поведении компилятора пользователи получат исключение NullReferenceException , чтобы избежать странной ситуации вызова метода для нулевого указателя. Эрик Ганнерсон объяснил это в своем блоге некоторое время назад: Почему C # всегда использует callvirt? У Gishu также есть хорошее объяснение в вопросе, относящемся к .

10
ответ дан 8 December 2019 в 12:57
поделиться

См. Информацию в моей записи в блоге .

Пример кода IL:

.class Program
{
  .method static void  Main(string[] args)
  {
    .entrypoint
    .locals init ([0] class Program p)
    ldloc.0 // but wait, it's still null!
    call   instance void Program::Awesome()
    ret
  } 

  .method instance void Awesome()
  {
    ldstr      "Awesome!"
    call       void [mscorlib]System.Console::WriteLine(string)
    ret
  } 

  .method public specialname rtspecialname instance void  .ctor()
  {
    ldarg.0
    call       instance void [mscorlib]System.Object::.ctor()
    ret
  }
}
5
ответ дан 8 December 2019 в 12:57
поделиться

CLR этого не требует, это деталь реализации языка. C # и VB.NET выполняют тест. C ++ / CLI - известный управляемый язык, который это позволяет. Пока метод экземпляра не ссылается на какие-либо члены класса, все пойдет не так. Если это так, исключение NullReferenceException будет сгенерировано как обычно, просто чтобы вам было сложно выяснить, почему.

#include "stdafx.h"

using namespace System;

ref class Test {
public:
    void Run() {
        Console::WriteLine("no problem");
    }
};

int main(array<System::String ^> ^args)
{
    Test^ obj = nullptr;
    obj->Run();
    return 0;
}
3
ответ дан 8 December 2019 в 12:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: