www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Wrong method called.

reply Dave <Dave_member pathlink.com> writes:
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
};
Jan 15 2006
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"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.
Mar 04 2006
next sibling parent alan <alan_member pathlink.com> writes:
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.
Mar 04 2006
prev sibling parent reply Brad Roberts <braddr puremagic.com> writes:
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
Mar 04 2006
parent Dave <Dave_member pathlink.com> writes:
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
Mar 05 2006