View mode: basic / threaded / horizontal-split · Log in · Help
January 15, 2006
Wrong method called.
I saw this elsewhere, but can't find the original and don't know if it was ever
reported in digitalmars.D.bugs or not.

Summary: Changing the order of class methods in an import file can result in the
wrong method called when the executable is built with the corresponding object
file. This happens on both Linux and Windows. On windows, the equivalent C++
code doesn't exhibit the same bug with DMC.

Build and run the following with:

\> dmd main.d c.d -ofmain
\> dmd main.d c.obj -version=_OBJ_ -ofmain_obj

\> main
method1()
method2()

\> main_obj
method2()
method1()

main.d:
-------
import c;

void main()
{
C c = new C;
c.method1();
c.method2();
}

c.d:
----
class C
{
version(_OBJ_)
{
void method2() { printf("method2()\n"); }
void method1() { printf("method1()\n"); }
}
else
{
void method1() { printf("method1()\n"); }
void method2() { printf("method2()\n"); }
}
}

C++ code:

\> dmc main.cpp c.cpp -omain_cpp
\> dmc main.cpp c.obj -D_OBJ_ -omain_cpp_obj

main.cpp:
---------
#include "c.h"

int main()
{
C *c = new C();
c->method1();
c->method2();

return 0;
}

c.cpp:
------
#include "c.h"
#include <stdio.h>

void C::method1() { printf("method1()\n"); }
void C::method2() { printf("method2()\n"); }

c.h:
----
class C
{
public:
#ifdef _OBJ_
virtual void method2();
virtual void method1();
#else
virtual void method1();
virtual void method2();
#endif
};
March 04, 2006
Re: Wrong method called.
"Dave" <Dave_member@pathlink.com> wrote in message 
news:dqef6s$2ovu$1@digitaldaemon.com...
>I saw this elsewhere, but can't find the original and don't know if it was 
>ever
> reported in digitalmars.D.bugs or not.
>
> Summary: Changing the order of class methods in an import file can result 
> in the
> wrong method called when the executable is built with the corresponding 
> object
> file.

It's not a bug. The order in the import file *must* match the order in the 
import's compiled object file. In the example presented, the order in the 
import file is changed (via a command line switch) to be different from what 
it was in the object file.
March 04, 2006
Re: Wrong method called.
In article <ducnmk$rv$4@digitaldaemon.com>, Walter Bright says...
>
>It's not a bug. The order in the import file *must* match the order in the 
>import's compiled object file. In the example presented, the order in the 
>import file is changed (via a command line switch) to be different from what 
>it was in the object file. 
>
>

dmd b.d a.d -c

dmd main.d a.obj b.obj
Error: AssertError Failure a.d(5)

dmd main.d b.obj a.obj
Error: AssertError Failure a.d(5)

============================================

dmd a.d b.d -c

dmd main.d a.obj b.obj
Bar.bar()

dmd main.d b.obj a.obj
Bar.bar()

============================================

dmd main.d a.d b.d
Bar.bar()

dmd main.d b.d a.d
Bar.bar()


OK, it's not a bug, it's a feature! I believe we now know why compiling object
modules seperately causes problems. Walter, I think you have a big problem here.
March 04, 2006
Re: Wrong method called.
On Sat, 4 Mar 2006, alan wrote:

> In article <ducnmk$rv$4@digitaldaemon.com>, Walter Bright says...
> >
> >It's not a bug. The order in the import file *must* match the order in the 
> >import's compiled object file. In the example presented, the order in the 
> >import file is changed (via a command line switch) to be different from what 
> >it was in the object file. 
> >
> >
> 
> dmd b.d a.d -c
> 
> dmd main.d a.obj b.obj
> Error: AssertError Failure a.d(5)
> 
> dmd main.d b.obj a.obj
> Error: AssertError Failure a.d(5)
> 
> ============================================
> 
> dmd a.d b.d -c
> 
> dmd main.d a.obj b.obj
> Bar.bar()
> 
> dmd main.d b.obj a.obj
> Bar.bar()
> 
> ============================================
> 
> dmd main.d a.d b.d
> Bar.bar()
> 
> dmd main.d b.d a.d
> Bar.bar()
> 
> 
> OK, it's not a bug, it's a feature! I believe we now know why compiling object
> modules seperately causes problems. Walter, I think you have a big problem here.

Careful.. don't confuse the original topic here with a different topic.  
The start of this is changing a module such that it doesn't match the 
.obj/.o being linked in.  Your example is order of linking.  If you lie to 
the compiler about the contents of the compiled code by changing the 
header, you're out of luck in general.

Later,
Brad
March 05, 2006
Re: Wrong method called.
In article <Pine.LNX.4.64.0603041438430.30259@bellevue.puremagic.com>, Brad
Roberts says...
>
>On Sat, 4 Mar 2006, alan wrote:
>
>> In article <ducnmk$rv$4@digitaldaemon.com>, Walter Bright says...
>> >
>> >It's not a bug. The order in the import file *must* match the order in the 
>> >import's compiled object file. In the example presented, the order in the 
>> >import file is changed (via a command line switch) to be different from what 
>> >it was in the object file. 
>> >
>> >
>> 
>> dmd b.d a.d -c
>> 
>> dmd main.d a.obj b.obj
>> Error: AssertError Failure a.d(5)
>> 
>> dmd main.d b.obj a.obj
>> Error: AssertError Failure a.d(5)
>> 
>> ============================================
>> 
>> dmd a.d b.d -c
>> 
>> dmd main.d a.obj b.obj
>> Bar.bar()
>> 
>> dmd main.d b.obj a.obj
>> Bar.bar()
>> 
>> ============================================
>> 
>> dmd main.d a.d b.d
>> Bar.bar()
>> 
>> dmd main.d b.d a.d
>> Bar.bar()
>> 
>> 
>> OK, it's not a bug, it's a feature! I believe we now know why compiling object
>> modules seperately causes problems. Walter, I think you have a big problem here.
>
>Careful.. don't confuse the original topic here with a different topic.  
>The start of this is changing a module such that it doesn't match the 
>.obj/.o being linked in.  Your example is order of linking.  If you lie to 
>the compiler about the contents of the compiled code by changing the 
>header, you're out of luck in general.
>

The OP was demonstrating a problem that can manifest itself in many ways with
versioning, making bugs caused by this hard to find and fix (because the program
might not crash). For example:

module a;
import b, std.stdio;
void main()
{
B b = new B;
writefln(b.foo(10));
}

module b;
class B
{
version(bar)
int bar(int x) { return x + x; }
int foo(int x) { return x * x; }
}

# dmd -c -version=bar b.d ; dmd -quiet a.d b.o ; a
20

Like the OP, DMC and also VC++ will call the correct function with equivalent
code.

I'm sure this will become a problem with library users not building their apps.
with the same compiler conditionals that were used to build the library. So if
it is something that wouldn't greatly complicate D compilers (or drastically
effect performance in calling virtual methods) then it would be a nice to have
change.

- Dave
Top | Discussion index | About this forum | D home