comparing pointers passed to and returned from funcs

bearophile bearophileHUGS at lycos.com
Tue Mar 1 14:53:41 PST 2011


spir:

> It seems to be the kind of stupid issue that will make you laugh about me. But 
> I cannot grasp and want to move forward anyway; so, let us be bold and take the 
> risk ;-)

Be bold. Understanding things is much more important. I've being wrong hundreds of times on D newsgroups, but I'm getting better.

> This fails! It even fails "doubly"...

Reduced program (and Walter thinks that avoiding printf-related bugs is not important. He's wrong. I use printf often enough in D):


import core.stdc.stdio: printf;
struct Foo {
    bool b;
    this(bool b_) { this.b = b_; }
}
enum Foo* TRUE = new Foo(true);
enum Foo* FALSE = new Foo(false);
Foo* not(Foo* op) {
    return (op == TRUE) ? FALSE : TRUE;
}
void main() {
    //assert(not(TRUE) == FALSE);
    printf("%x\n", TRUE);
    printf("%x\n", FALSE);
    printf("%x\n", not(TRUE));
    printf("%x\n", not(not(TRUE)));
}


> Here, I operate on the structs instead of on the pointers, both to perform the 
> operation and in the assert. What I understand is: all happens like if D would 
> copy the pointed structs on parameter passing and on return. I thought D would 
> only copy the pointers (in both directions), which would let me compare said 
> pointers directly.
> What do I miss?

DMD is not copying the structs, just pointers.

I think it's happening something like with enum associative arrays. Pointers are run-time things. You are asking for a new at compile-time. This is the asm produced by that program (-O -release):


_D4test3Foo6__ctorMFNcbZS4test3Foo	comdat
		push	EAX
		mov	CL,8[ESP]
		mov	[EAX],CL
		pop	ECX
		ret	4

_D4test3notFPS4test3FooZPS4test3Foo	comdat
L0:		push	EAX
		mov	ECX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	EAX
		push	EBX
		push	1
		push	ECX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		push	1
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		cmp	EAX,8[ESP]
		jne	L3D
		mov	EDX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	1
		push	EDX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		push	0
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		jmp short	L56
L3D:		mov	EBX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	1
		push	EBX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		push	1
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
L56:		pop	EBX
		add	ESP,8
		ret

__Dmain	comdat
L0:		push	EAX
		mov	EAX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	EBX
		push	ESI
		push	1
		push	1
		push	EAX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		mov	ECX,offset FLAT:_DATA
		push	EAX
		push	ECX
		call	near ptr _printf
		mov	EDX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	0
		push	1
		push	EDX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		mov	EBX,offset FLAT:_DATA
		push	EAX
		push	EBX
		call	near ptr _printf
		mov	ESI,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	1
		push	1
		push	ESI
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		call	near ptr _D4test3notFPS4test3FooZPS4test3Foo
		push	EAX
		push	EBX
		call	near ptr _printf
		push	1
		push	1
		push	ESI
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		call	near ptr _D4test3notFPS4test3FooZPS4test3Foo
		call	near ptr _D4test3notFPS4test3FooZPS4test3Foo
		push	EAX
		push	EBX
		call	near ptr _printf
		add	ESP,020h
		xor	EAX,EAX
		pop	ESI
		pop	EBX
		pop	ECX
		ret


My suspect is confirmed, DMD is acting as with enum associative arrays. This is a compiler bug. DMD has to act correctly and not create a struct every time, or it has to give a compile-time error. Not this mess.

Bye,
bearophile


More information about the Digitalmars-d-learn mailing list