开发者

Is there a declaring-type object pointer on stack?

Let's say I have:

class Animal { }
class Dog : Animal { }

And in the main method:

Dog dog = new Dog();
Animal animal = dog;

Now there is one instance of Dog on the heap, and two variables on the stack, with the same reference stored in them. The next step is

   //Try to invoke dog.Bark() programatically
   //Try to invoke animal.Bark() programatically

The开发者_JAVA百科 latter fails at run time, because animal hasn't a Bark method. So there must be something different on stack, for the two variables. What's the difference resulting in the run time error?


You are correctly deducing a number of implementation details.

Before going into those details, some terms. There are three kinds of storage:

  • unmanaged storage
  • managed storage
  • temporary storage

Unmanaged storage is outside the scope of your question. Managed storage is what we'll call "the heap". Temporary storage is "the stack" or registers if the jitter is clever and registers are available, but as a simplifying assumption lets ignore registers and just call the temporary storage pool "the stack".

There are four kinds of types:

  • unmanaged pointers
  • value types
  • references, aka, managed pointers
  • the actual instances of reference types

Unmanaged pointers are outside the scope of your question. C# allows you to manipulate references ("managed pointers") and value types directly; contents of reference type instances are only manipulated via references and are always on the heap in the CLR implementation. (Nothing stops the jitter from creating an instance of reference type on the stack if it has enough smarts to know that the object never needs garbage collection and does not survive the method, but in practice our jitters do not do so to my knowledge.)

The other three kinds of things can be on the stack or the heap as necessary, depending on their lifetimes.

In my main method an instance of Dog is created and assigned to a variable named dog. I know what happens on the heap, assuming it locates from the address 0x00FFFF.

You are assuming (correctly) that managed references are implemented as addresses in a flat 32 bit address space. (That would not actually be a legal heap address, but we'll let it slide.) Of course, an implementation of the CLR need not use raw addresses as references. They could be opaque handles into a table controlled by the GC, for example.

Currently I only know on the stack the space for dog has its value 0x00FFFFF, but I'm 100% sure somewhere else in the space for dog has its declaring type.

By its "declaring" type I think you mean the actual runtime type of the instance, Dog. This is a confusing use of "declaring". Instances are not "declared"; instances are " allocated". Variables are "declared" and the variable has the declared type "Animal".

Yes, somewhere in the actual instance data allocated for "new Dog()" there is a "token" that describes the runtime type of the object. If the exact details of how the token works are important to you, ask another question.

I want to know a detail explaination of the stack space for dog, currently I know there is a reference address there, anything else?

Your question is ambiguous because there are two variables on the stack and neither of them are named "dog".

At runtime the stack space just contains the managed reference to the heap space allocated for the instance. The C# compiler knows that the stack space for dog1 was of compile-time type managed-reference-to-Animal and the stack space for dog2 was of compile time type managed-reference-to-Dog. The jitter therefore knows that information as well. The jitter keeps information about that in its own data structures; it does not pollute the stack. The jitter can keep this information around for optimizations, or for debugging purposes. Or it can throw it away if it doesn't need that information anymore.

This again is an implementation detail; the jitter is perfectly free to put any additional information on the stack it pleases.


References are located on stack and CLR knows kind of reference it is working with. The memory pointed by the reference is allocated on the heap. In your example both references could point to the same place in memory but CLR interprets the differently because of reference type.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜