Bug 3604 – extern(C) callable function with array parameters broken
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
druntime
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2009-12-10T10:17:00Z
Last change time
2015-06-09T01:28:19Z
Keywords
wrong-code
Assigned to
sean
Creator
witold.baryluk+d
Comments
Comment #0 by witold.baryluk+d — 2009-12-10T10:17:12Z
I found a regression in 2.037. It was working in 2.032.
import core.sys.posix.unistd : pipe;
void main() {
int[2] input, output;
writefln("input: %s", input);
writefln("input.ptr: %s", input.ptr);
writefln("cast input: %s", cast(char*)input);
ttt(input);
if (pipe(input) != 0) {
throw new Exception("can't create input pipe");
} else {
writeln("ok");
}
}
extern(C) int ttt(int[2] x) {
writefln("x = %s", x);
writefln("x[0] = %s", x[0]);
writefln("x[1] = %s", x[1]);
return 0;
}
this programs print:
====
input: 0 0
input.ptr: BF85E068
cast input: BF85E068
x = 0 0
x[0] = 0
x[1] = 0
object.Exception: can't create input pipe
====
but should:
====
input: 0 0
input.ptr: BF85E068
cast input: BF85E068
x = BF85E068
x[0] = 0
x[1] = 0
ok
====
Comment #1 by witold.baryluk+d — 2009-12-10T10:31:47Z
In, 2.032 (just tested) it returns:
$ ./bug3604
input: 0 0
input.ptr: BFA00CB8
cast input: BFA00CB8
x = 0 0
x[0] = 0
x[1] = 0
ok
$
So not exactly what I written, but pipe is working.
So i tested it more precisly:
bug3604.d:
extern(C) int tttc(int[2] x);
void main() {
int[2] input;
tttc(input);
}
bug3604c.c:
#include <stdio.h>
int tttc(int x[2]) {
printf("just in C\n");
printf("x=%p\n", x);
printf("x[0]=%d\n", x[0]);
printf("x[1]=%d\n", x[1]);
printf("back from C\n");
}
# gcc -c bug3604c.c
# dmd2.032 bug3604.d bug3604c.o
# ./bug3604
just in C
x=0xbf988ff8
x[0]=0
x[1]=0
back from C
# dmd2.037 bug3604.d bug3604c.o
# ./bug3604
just in C
x=(nil)
Segmentation fault
#
So it is regression.
In `strace` for "pipe" example I see for 2.032:
pipe([3, 4]) = 0
and for 2.037:
pipe(0) = -1 EFAULT (Bad address)
So it also passes NULL pointer (jiust like in tttc function) .
Comment #2 by lutger.blijdestijn — 2009-12-10T13:36:16Z
Comment #3 by witold.baryluk+d — 2009-12-11T06:22:49Z
Changing declaration of pipe to
extern(C) int pipe(int*);
will make that D type system have less information than previous.
currently, if I would write:
extern(C) int pipe(int[2]);
int[1] input;
pipe(input);
it will fail to compile because of wrong type.
But with:
extern(C) int pipe(int*);
int[1] input;
pipe(input.ptr);
it will compile without any error.
I see many other functions, in core which takes array of different sizes.
How about just interpreting array parametern in extern(C) function as being passed via reference. I don't see what was wrong in previous approach. It gives some more verbosity to error messages.
If anyway this is new intended behaviour, please document it and fix all headers in core.* and other extern(C) headers.
Comment #4 by schveiguy — 2009-12-11T06:40:58Z
What about using ref int[2] instead?
I just tested with your code modifying the signature and it works:
[steves@steveslaptop testd]$ cat bug3604.d
extern(C) int tttc(ref int[2] x);
void main() {
int[2] input;
tttc(input);
}
[steves@steveslaptop testd]$ cat bug3604c.c
#include <stdio.h>
int tttc(int x[2]) {
printf("just in C\n");
printf("x=%p\n", x);
printf("x[0]=%d\n", x[0]);
printf("x[1]=%d\n", x[1]);
printf("back from C\n");
}
[steves@steveslaptop testd]$ gcc -c bug3604c.c
[steves@steveslaptop testd]$ ../dmd2.037/linux/bin/dmd bug3604.d bug3604c.o
[steves@steveslaptop testd]$ ./bug3604
just in C
x=0xbffa06e0
x[0]=0
x[1]=0
back from C
I think this better captures the correct signature than what I suggested in the post.
Comment #5 by witold.baryluk+d — 2009-12-15T16:47:26Z
Ah, yes
ref T[];
this sounds good. I will reassign this bug to druntime then, and hopfully trivial fixes will be on next release.
PS. I just checked changlogs and there are nothing about this change in compiler or spec. :/
Maybe small update to http://digitalmars.com/d/2.0/interfaceToC.html ?
Comment #6 by bugzilla — 2010-01-04T14:47:18Z
Good idea, I've updated interfaceToC.html
Comment #7 by witold.baryluk+d — 2010-01-21T05:44:35Z
Thanks.
Functions like
sys.posix.unistd: pipe, encrypt
sys.posix.stdlib: Xseed48, {e,j,n}rand48, lcong48
sys.posix.poll: poll
sys.posix.sys.time: utimes
sys.posix.sys.socket : socketpair
are currently affected in druntime (from 2.039).
Comment #8 by bugzilla — 2010-02-26T10:36:17Z
I ran into the problem with core.sys.posix.unistd.pipe() today. The following grep should have tracked down most of the problematic declarations:
$ grep -r '(.*\w\+[[][0-9]' core/*
core/sys/posix/sys/socket.d:int socketpair(int, int, int, int[2]);
core/sys/posix/sys/socket.d: int socketpair(int, int, int, int[2]);
core/sys/posix/sys/socket.d: int socketpair(int, int, int, int[2]);
core/sys/posix/sys/socket.d: int socketpair(int, int, int, int[2]);
core/sys/posix/sys/time.d:int utimes(in char*, in timeval[2]); // LEGACY
core/sys/posix/sys/time.d: int utimes(in char*, in timeval[2]); // LEGACY
core/sys/posix/sys/time.d: int utimes(in char*, in timeval[2]);
core/sys/posix/sys/time.d: int utimes(in char*, in timeval[2]);
core/sys/posix/stdlib.d:double erand48(ushort[3]);
core/sys/posix/stdlib.d:c_long jrand48(ushort[3]);
core/sys/posix/stdlib.d:void lcong48(ushort[7]);
core/sys/posix/stdlib.d:c_long nrand48(ushort[3]);
core/sys/posix/stdlib.d:ushort seed48(ushort[3]);
core/sys/posix/stdlib.d: double erand48(ushort[3]);
core/sys/posix/stdlib.d: c_long jrand48(ushort[3]);
core/sys/posix/stdlib.d: void lcong48(ushort[7]);
core/sys/posix/stdlib.d: c_long nrand48(ushort[3]);
core/sys/posix/stdlib.d: ushort seed48(ushort[3]);
core/sys/posix/stdlib.d: double erand48(ushort[3]);
core/sys/posix/stdlib.d: c_long jrand48(ushort[3]);
core/sys/posix/stdlib.d: void lcong48(ushort[7]);
core/sys/posix/stdlib.d: c_long nrand48(ushort[3]);
core/sys/posix/stdlib.d: ushort seed48(ushort[3]);
core/sys/posix/stdlib.d: double erand48(ushort[3]);
core/sys/posix/stdlib.d: c_long jrand48(ushort[3]);
core/sys/posix/stdlib.d: void lcong48(ushort[7]);
core/sys/posix/stdlib.d: c_long nrand48(ushort[3]);
core/sys/posix/stdlib.d: ushort seed48(ushort[3]);
core/sys/posix/unistd.d:int pipe(int[2]);
core/sys/posix/unistd.d:void encrypt(char[64], int);
core/sys/posix/unistd.d: void encrypt(char[64], int);
core/sys/posix/unistd.d: void encrypt(char[64], int);
(I've removed a few false positives in the above.)
Comment #9 by schveiguy — 2010-05-17T06:34:35Z
*** Issue 4199 has been marked as a duplicate of this issue. ***
Comment #10 by braddr — 2010-06-15T02:09:04Z
fixed in 2.047
Comment #11 by bugzilla — 2010-06-15T04:47:33Z
It seems only the ones in stdlib and unistd have been fixed, and not the ones in sys.socket and sys.time.