[Issue 22318] New: Calling virtual extern(C++) functions crashing or wrong
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Sat Sep 18 11:37:13 UTC 2021
https://issues.dlang.org/show_bug.cgi?id=22318
Issue ID: 22318
Summary: Calling virtual extern(C++) functions crashing or
wrong
Product: D
Version: D2
Hardware: x86_64
OS: Linux
Status: NEW
Severity: enhancement
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: tim.dlang at t-online.de
While working on issue 22287 I found some other problems with extern(C++)
classes with constructors.
//////////////// test.d //////////////////
extern(C++):
class A
{
this(int i);
~this();
int i;
}
interface I
{
int f() const;
}
class B : A, I
{
this(int i);
override int f() const;
}
class D : B
{
this(int i)
{
super(i);
}
override int f() const
{
return i + 42;
}
}
I createIFromCPP(char type, int i);
B createBFromCPP(char type, int i);
D createDFromCPP(int i);
I createIFromD(char type, int i)
{
switch (type)
{
case 'B':
return new B(i);
case 'D':
return new D(i);
default:
return null;
}
}
B createBFromD(char type, int i)
{
switch (type)
{
case 'B':
return new B(i);
case 'D':
return new D(i);
default:
return null;
}
}
D createDFromD(int i)
{
return new D(i);
}
void runCPPTests();
extern(D) void main()
{
{
D d = new D(100);
assert(d.f() == 142); // works
}
{
I i = createIFromCPP('D', 100);
//assert(i.f() == 142); // fails, because i.f() returns 122
}
{
B b = createBFromCPP('D', 100);
//assert(b.f() == 142); // Segmentation fault
}
{
D d = createDFromCPP(100);
//assert(d.f() == 142); // Segmentation fault
}
runCPPTests();
}
//////////////// test.cpp ////////////////
#include <assert.h>
class A
{
public:
A(int i);
virtual ~A();
int i;
};
class I
{
public:
virtual int f() const = 0;
};
class B : public A, public I
{
public:
B(int i);
virtual int f() const;
};
class D : public B
{
public:
D(int i);
virtual int f() const;
};
A::A(int i) : i(i)
{
}
A::~A()
{
}
B::B(int i) : A(i)
{
}
int B::f() const
{
return i + 22;
}
I *createIFromCPP(char type, int i)
{
switch (type)
{
case 'B':
return new B(i);
case 'D':
return new D(i);
default:
return 0;
}
}
B *createBFromCPP(char type, int i)
{
switch (type)
{
case 'B':
return new B(i);
case 'D':
return new D(i);
default:
return 0;
}
}
D *createDFromCPP(int i)
{
D *d = new D(i);
return d;
}
I *createIFromD(char type, int i);
B *createBFromD(char type, int i);
D *createDFromD(int i);
void runCPPTests()
{
{
D *d = new D(100);
assert(d->f() == 142); // Segmentation fault
}
{
I *i = createIFromD('D', 100);
assert(i->f() == 142); // fails, because i.f() returns 122
}
{
B *b = createBFromD('D', 100);
assert(b->f() == 142); // works
}
{
D *d = createDFromD(100);
assert(d->f() == 142); // works
}
}
//////////////////////////////////////////
The issue exists under Linux and Windows. The comments describe the behaviour
under Linux x86_64. Sometimes the call results in a crash. Other times it seems
to call the function of a parent class. Some calls also work as expected.
If the constructors are removed and A.i is set after creating the object, it
works as expected.
--
More information about the Digitalmars-d-bugs
mailing list