Should opEquals be removed from object? (Was: Re: How to check

Daniel Keep daniel.keep.lists at gmail.com
Mon Aug 27 18:59:36 PDT 2007



Sean Kelly wrote:
> [snip]
> 
> opEquals needs to be in Object because it is used by the AA code.
> However, it could be changed to simply throw an exception, thus
> requiring users to override it.
> 
> Sean

Just a note: I just re-read what you said and realised you meant it
should throw an exception in all cases.  I thought you meant if you were
trying to compare to null (duh).

I'm not sure if I'm for or against that idea, but it would certainly fix
the problem.  Especially if the error was "Use the is operator, and read
the documentation!" :P

(Although, that doesn't help us if they haven't worked out they need to
use 'new', but you can't have everything :P)

	-- Daniel

Just because I put a lot[1] of effort into it, here's what I was *going*
to write:

[1] When I say "a lot" I mean "had to write, compile, debug and
disassemble a test program immediately after waking up."  I deserve a
*medal* for that!

module nullobj;

class Foo
{
    int opEquals(Object other)
    {
        throw new Exception("AARGH, GOODBAI KRUUL WURLD!");
    }
}

void main()
{
    Foo foo;
    bool foundit = cast(bool)(foo == null);
}

-----

> dmd nullobj && nullobj
Error: Access Violation

See, it already throws an exception! :P  Let's see what happens when we
disassemble the code in main:

nullobj.d:11 void main()
0040204c: c8080000                enter 0x8, 0x0
nullobj.d:13     Foo foo;
00402050: 31c0                    xor eax, eax
00402052: 8945f8                  mov [ebp-0x8], eax
nullobj.d:14     bool foundit = cast(bool)(foo == null);
00402055: 50                      push eax
00402056: 8b08                    mov ecx, [eax]
00402058: ff5114                  call dword near [ecx+0x14]
0040205b: f7d8                    neg eax
0040205d: 19c0                    sbb eax, eax
0040205f: f7d8                    neg eax
00402061: 8845fc                  mov [ebp-0x4], al
00402064: 31c0                    xor eax, eax
nullobj.obj
00402066: c9                      leave
00402067: c3                      ret

Ok, look at the call and the lines above it.  That's the line where we
call opEquals.  But notice how we're doing it?  We're calling it by
using one of the vtable functions, stored as an offset from the start of
the object.  But the object's null, so when we try to work out where the
opEquals function is... BOOM.

So yes, we *can* already have opEquals throw an exception if the
object's null.  It just has to be a segfault, since if the object's
null, we can't find opEquals.

As an aside, I love ddbg ^_^



More information about the Digitalmars-d mailing list