memcpy() comparison: C, Rust, and D
Richard Delorme via Digitalmars-d
digitalmars-d at puremagic.com
Tue Jan 31 15:00:21 PST 2017
On Tuesday, 31 January 2017 at 19:20:40 UTC, Walter Bright wrote:
> On 1/31/2017 5:50 AM, Richard Delorme wrote:
>> Well, I would not have taken memcpy as an example in favor of
>> D. Good C
>> compilers (like gcc) know what memcpy does and are able to
>> optimize it according
>> to its arguments. DMD may know better about memcpy through its
>> declaration but
>> does not make any use about it.
>
> That may be true, but is not my point. The compiler cannot have
> built in knowledge of every function. I just used memcpy() as
> an example because it is extremely well known.
>
> As for making use of the type signature information, DMD uses
> it to check the memory safety of arguments supplied to
> memcpy(), something gcc does not do.
May we have an example of how the memory safety of arguments
supplied to memcpy is checked in a way gcc cannot do?
I was thinking of the return attribute, that prevents for example
to return the address of a local variable through a call to
memcpy:
module dmemcpy;
import std.stdio;
extern (C) @system nothrow @nogc
pure void* memcpy(return void* s1, const scope void *s2, size_t
n);
void *copy(const scope void *c, size_t n) {
byte [16] d;
return memcpy(&d[0], c, n);
}
void main() {
byte [16] a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15];
byte *b = cast (byte*) copy(&a[0], 8);
foreach (i; 0..16) write(b[i], ", ");
writeln();
}
// ------- end ----------
$ dmd dmemcpy2.d
dmemcpy2.d(9): Error: escaping reference to local variable d
without the return attribute in memcpy declaration, dmd does not
issue this error message.
The equivalent program in C:
#include <string.h>
#include <stdio.h>
void *copy(const void *c, size_t n) {
char d[16];
return memcpy(d, c, n);
}
int main(void) {
char a[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15};
char *b = copy(a, 8);
for (int i = 0; i < 16; ++i) printf("%d ", b[i]);
putchar('\n');
}
// --- end of program ----
Compiling with gcc:
$ gcc memcpy2.c -O2 -W
memcpy2.c: In function 'copy':
memcpy2.c:6:9: warning: function returns address of local
variable [-Wreturn-local-addr]
return memcpy(d, c, n);
^~~~~~~~~~~~~~~
memcpy2.c:5:7: note: declared here
char d[16];
Or with clang:
$ clang memcpy2.c --analyze
memcpy2.c:6:2: warning: Address of stack memory associated with
local variable 'd' returned to caller
return memcpy(d, c, n);
^~~~~~~~~~~~~~~~~~~~~~
So, even without a return attribute, good C compilers like gcc or
clang are able to emit a warning message.
I am not really convinced by the necessity of attributes to
enhance memory safety. I think the compiler should be able to
check for safety without the user to ask it. Having to write
attributes is a burden put on the user of the compiler. What if I
forget to write an attribute? I just mistakenly make my program
unsafe :-( Having a compiler checking for potential errors
without me asking for is much safer in my humble opinion.
--
Richard Delorme
More information about the Digitalmars-d
mailing list