使用 callvirt 调用 base.ToString() 如何导致 StackOverflow 异常?

发布于 2024-08-20 22:32:12 字数 469 浏览 4 评论 0原文

IL提供了两种调用函数的语句,即call和callvirt。 Call 用于调用非虚函数或静态函数或编译器不想对引用进行空检查的任何函数。

callvirt 用于调用虚函数,也调用非虚函数,因为编译器在运行时对引用进行空检查。

现在,在通过 C# 查看 CLR 时,我发现了以下示例。

internal class SomeClass
{
   public override String ToString()
   {
      return base.ToString();
   }
}

现在 ToString() 是虚函数,但是编译器为其生成调用指令是可以的。但是 Jeffrey 提到为什么不生成 callvirt 的原因是因为在这种情况下 ToString() 会被递归调用并会导致 StackOverFlow 异常,我试图理解但无法理解这个想法?谁能解释为什么它会导致递归调用?

谢谢..

IL offers two statements for calling functions, i.e. call and callvirt. Call is used to call the non-virtual or static functions or any function where compiler doesn't want to do a null check on the reference.

callvirt is used to call virtual functions, non-virtual functions are also called, since compiler does a null check on the reference at run time.

Now while going through CLR via C# i found following example.

internal class SomeClass
{
   public override String ToString()
   {
      return base.ToString();
   }
}

Now ToString() is virtual function, but compiler generates the call instruction for it its ok.But the reason that Jeffrey mentioned that why callvirt is not generated because in that case the ToString() would be called recursively and will cause the StackOverFlow Exception, I tried to understand but was unable to wrap my mind around this idea ? Can anyone explain why it will cause a recursive call?

Thanks..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

開玄 2024-08-27 22:32:12

据我所知,如果编译器生成 callvirt,就会发生 stackoverflow 异常,因为:

某些代码调用继承自类 objectsomeclass 类型的对象的 ToString。
*somclass 的 ToString 方法调用其基类(object)的 ToString 方法。

如果此调用是虚拟的,则不会导致从以下位置调用 ToString类 object 但在实际类的 ToString 调用中(即 SomeClass),

那么你将处于不定式循环中,因为整个事情将从 new 开始。现在。

from what I believe, a stackoverflow exception would happen if the compiler generated callvirt because:

Some code calls ToString of an object of type someclass which inherits from the class object.
The ToString of *somclass" method calls the ToString Method of it's base class which is object.

If this call would be virtual, it wouldn't result in call of ToString from the class object but in a call of ToString of the actuall class (which is SomeClass).

Then you whould be in an infinitive loop, as the whole thing would start from new now.

隱形的亼 2024-08-27 22:32:12

对特定超类(在本例中为 System.Object,因为您编写了 base)的显式调用不得为 callvirt code> 因为这可能导致堆栈溢出。

一些 C# 伪代码:

internal class SomeClass
{
   public override String ToString()
   {
       // The "return base.ToString()" call could produce one of these two possibilities:

       // This will NOT go through the class hierarchy, searching for a overwritten function
       // called ToString
       call and return System.Object::ToString()

       // But this WILL, thus calling SomeClass::ToString() recursively, so this is wrong
       // and would lead to a stack overflow
       callvirt and return System.Object::ToString()
   }
}

希望这就是您的意思。

The explicit call to a specific super class (in this case System.Object because you wrote base) must not be callvirt because that can lead to a stack overflow.

Some C# pseudocode:

internal class SomeClass
{
   public override String ToString()
   {
       // The "return base.ToString()" call could produce one of these two possibilities:

       // This will NOT go through the class hierarchy, searching for a overwritten function
       // called ToString
       call and return System.Object::ToString()

       // But this WILL, thus calling SomeClass::ToString() recursively, so this is wrong
       // and would lead to a stack overflow
       callvirt and return System.Object::ToString()
   }
}

Hope that is what you meant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文