www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Null pointer in __vptr

reply frame <frame86 live.com> writes:
Got a suspicious interface instance in the debugger and question 
myself:

Is a null pointer entry in the __vptr[] valid or always a sign 
for corruption/wrong cast somewhere? thx
Nov 19 2021
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Friday, 19 November 2021 at 15:37:59 UTC, frame wrote:
 Is a null pointer entry in the __vptr[] valid or always a sign 
 for corruption/wrong cast somewhere? thx
The `destroy` function (as well as other class destruction) will null out the whole vtable to help make use-after-free an obvious error. Possible that happened to you.
Nov 19 2021
parent reply frame <frame86 live.com> writes:
On Friday, 19 November 2021 at 15:46:41 UTC, Adam D Ruppe wrote:

 The `destroy` function (as well as other class destruction) 
 will null out the whole vtable to help make use-after-free an 
 obvious error. Possible that happened to you.
So, a partial nulled table shouldn't exist, right? like this: __vptr[0]: address __vptr[1]: 0000000 __vptr[2]: address __vptr[3]: address __vptr[4]: address __vptr[5]: address ... Because 0 should point to the object instance and next offsets are pointers to the member functions, correct?
Nov 19 2021
next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Friday, 19 November 2021 at 18:04:17 UTC, frame wrote:
 So, a partial nulled table shouldn't exist, right? like this:
Indeed. I've gotten that before as a result of a compiler bug... I had an abstract method that wasn't implemented but the compile time error got swallowed by a bug and thus the null method made its way to the binary. I think that bug was fixed.... but still you might want to check your code for the `abstract` keyword and ensure they are legit implemented in your cases.
Nov 19 2021
parent reply frame <frame86 live.com> writes:
On Friday, 19 November 2021 at 18:14:03 UTC, Adam D Ruppe wrote:

 I've gotten that before as a result of a compiler bug... I had 
 an abstract method that wasn't implemented but the compile time 
 error got swallowed by a bug and thus the null method made its 
 way to the binary.
You got it! It was an abstract class involved and the method signature was just wrong, but no compile error. Thanks!
Nov 19 2021
parent reply bauss <jj_1337 live.dk> writes:
On Friday, 19 November 2021 at 20:27:11 UTC, frame wrote:
 On Friday, 19 November 2021 at 18:14:03 UTC, Adam D Ruppe wrote:

 I've gotten that before as a result of a compiler bug... I had 
 an abstract method that wasn't implemented but the compile 
 time error got swallowed by a bug and thus the null method 
 made its way to the binary.
You got it! It was an abstract class involved and the method signature was just wrong, but no compile error. Thanks!
Seems like it was only partially fixed then, specifically for missing abstract methods, but not whether the signature was correct or not. Seems like a critical bug to me.
Nov 22 2021
parent frame <frame86 live.com> writes:
On Monday, 22 November 2021 at 13:21:22 UTC, bauss wrote:

 Seems like it was only partially fixed then, specifically for 
 missing abstract methods, but not whether the signature was 
 correct or not.

 Seems like a critical bug to me.
At least it's still present in dmd 2.098.
Nov 22 2021
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/19/21 10:04 AM, frame wrote:
 On Friday, 19 November 2021 at 15:46:41 UTC, Adam D Ruppe wrote:

 The `destroy` function (as well as other class destruction) will null
 out the whole vtable to help make use-after-free an obvious error.
 Possible that happened to you.
So, a partial nulled table shouldn't exist, right? like this: __vptr[0]: address __vptr[1]: 0000000 __vptr[2]: address __vptr[3]: address __vptr[4]: address __vptr[5]: address .... Because 0 should point to the object instance
I am not sure that's correct. The way I picture it, the code reaches the __vptr by following a pointer; so it's already known. Additionally, I am under the impression that there is only one __vptr for a given type, which all class objects of that type point to.
 and next offsets are pointers to the member functions, correct?
My understanding is that all entries are that. Ali
Nov 19 2021
parent reply frame <frame86 live.com> writes:
On Friday, 19 November 2021 at 21:09:16 UTC, Ali Çehreli wrote:

 I am not sure that's correct. The way I picture it, the code 
 reaches the __vptr by following a pointer; so it's already 
 known. Additionally, I am under the impression that there is 
 only one __vptr for a given type, which all class objects of 
 that type point to.
I think this is true for an object instance. But from an interface instance, the object instance must be accessible somewhere? This is also how I would read the doc:
 The vtbl[0] entry is a pointer to the corresponding instance of 
 the object.Interface class.
On the other hand, I don't know what the debugger is really showing here - it's printed as void* array and I wonder where it gets the length of the array.
Nov 20 2021
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/20/21 7:19 AM, frame wrote:

 I think this is true for an object instance. But from an interface
 instance, the object instance must be accessible somewhere?
Everything needed is available from the pointer to a class object (or interface). There are some offset arithmetic involved to get to the right vtbl pointer but the pointer of an object cannot be stored anywhere in the vtbl because there is just one vtbl but very many objects.
 This is also
 how I would read the doc:

 The vtbl[0] entry is a pointer to the corresponding instance of the
 object.Interface class.
That is from https://dlang.org/spec/abi.html What they mean with object.Instance is the following definition I find e.g. in my /usr/include/dmd/druntime/import/object.d file: /** * Information about an interface. * When an object is accessed via an interface, an Interface* appears as the * first entry in its vtbl. */ struct Interface { TypeInfo_Class classinfo; /// .classinfo for this interface (not for containing class) void*[] vtbl; size_t offset; /// offset to Interface 'this' from Object 'this' } So, the first entry is a pointer to that struct. The ABI document mentions "pointer to instance of TypeInfo" as well, which is defined in the same object.d as well: /** * Runtime type information about a type. * Can be retrieved for any type using a * $(GLINK2 expression,TypeidExpression, TypeidExpression). */ class TypeInfo { // ... } Ali
Nov 20 2021
parent frame <frame86 live.com> writes:
On Sunday, 21 November 2021 at 02:43:12 UTC, Ali Çehreli wrote:

 There are some offset arithmetic involved to get to the right 
 vtbl pointer but the pointer of an object cannot be stored 
 anywhere in the vtbl because there is just one vtbl but very 
 many objects.
Ok, so they mean by instance is only one instance by type but not data instance, got it.
Nov 21 2021