digitalmars.D - Pure, Nothrow in Generic Programming
- dsimcha (19/19) Nov 22 2009 One issue that should ideally be resolved before D2 is finalized that I ...
- Simen kjaeraas (4/30) Nov 25 2009 Votes++;
- Don (10/32) Nov 25 2009 That sounds reasonable to me. Already in many cases, the function body
- dsimcha (5/34) Nov 25 2009 I would say that @safe doesn't make much sense. What if you're implemen...
- Walter Bright (3/7) Nov 27 2009 A safe function is only safe if the parameters passed to it are valid.
- dsimcha (8/15) Nov 27 2009 I think you misunderstood the argument. memcmp() could be @trusted if f...
- Don (16/32) Nov 27 2009 It seems to me that one of the most important features of SafeD is that
- Walter Bright (2/10) Nov 27 2009 Exactly. You said it better than me!
- Walter Bright (6/12) Nov 27 2009 memcmp() could be marked @trusted, but it should not be. This is because...
- BCS (6/9) Nov 27 2009 I think that's backwards. There's no way memcmp can be sure it's argumen...
- Andrei Alexandrescu (9/28) Nov 27 2009 Hm, if we think of it, memcmp can be @safe no problem. This is beacuse
- Don (6/41) Nov 27 2009 Although Walter had previously talked about making @safe a little
- dsimcha (4/45) Nov 27 2009 Quick question about the eliminating undefined behavior thing: Isn't ov...
- Denis Koroskin (3/54) Nov 27 2009 I don't think integer overflow could be considered an undefined behavior...
- bearophile (6/8) Nov 27 2009 Computers are (mostly) deterministic, so in a certain sense everything t...
- dsimcha (3/58) Nov 27 2009 What about int.max + 1? I specifically mentioned **signed** integers be...
- Walter Bright (3/5) Nov 27 2009 It's undefined behavior in C because C supports ones-complement
- bearophile (8/10) Nov 27 2009 I have explained LLVM devs how to speed-up some of those runtime checks.
- Walter Bright (3/5) Nov 27 2009 No. On every 2's complement machine I've ever heard of, the behavior is
- Andrei Alexandrescu (6/49) Nov 27 2009 I think it would be implementation-defined behavior - in case (b) memcmp...
- Walter Bright (2/6) Nov 27 2009 How could it?
- Andrei Alexandrescu (16/24) Nov 27 2009 The value itself does not matter. The point is the behavior is not
- Walter Bright (4/7) Nov 27 2009 Makes sense. But I'd still want to make it not @safe, by using a more
- Andrei Alexandrescu (18/26) Nov 27 2009 It's funny how we are trading places. Til now I was the stickler for saf...
- torhu (10/10) Nov 27 2009 I have a feeling that the safeD thing is a bit premature. I'm only
- Denis Koroskin (4/30) Nov 27 2009 Points 2 and 3 introduce undefined behavior, which is not allowed in Saf...
- Andrei Alexandrescu (3/42) Nov 27 2009 s/undefined/implementation-defined/
- Rainer Deyke (14/19) Nov 27 2009 Behavior is only implementation-defined if the implementation actually
- Andrei Alexandrescu (6/25) Nov 30 2009 I only know of writing to cause actual device writing, so I'd be
One issue that should ideally be resolved before D2 is finalized that I meant to bring up here a long time ago is how to handle pure and nothrow in generic functions. For example: T max(T)(T lhs, T rhs) { return (lhs > rhs) ? lhs : rhs; } Obviously, if T is an int, max can be pure nothrow. However, if T is some user defined type, then who knows? I've run into a few cases where I'm writing a pure function that needs to call something simple like std.algorithm.max() on an int or a float and invariably I end up just rewriting a max function for my specific type and marking it as pure nothrow. This is obviously a suboptimial solution. Since the source needs to be available anyhow for templates to be usable, my proposal would be for pure/nothrow functions to be able to call templated functions that are not marked as pure/nothrow as long as they would compile if marked pure/nothrow. Also, I think that we need to establish a strong convention, for objects, that opCmp, opEquals and a few other "standard" functions should always be const pure nothrow, and that it is acceptable for any library code (mixins, etc.) to assume this.
Nov 22 2009
On Sun, 22 Nov 2009 20:34:21 +0100, dsimcha <dsimcha yahoo.com> wrote:One issue that should ideally be resolved before D2 is finalized that I meant to bring up here a long time ago is how to handle pure and nothrow in generic functions. For example: T max(T)(T lhs, T rhs) { return (lhs > rhs) ? lhs : rhs; } Obviously, if T is an int, max can be pure nothrow. However, if T is some user defined type, then who knows? I've run into a few cases where I'm writing a pure function that needs to call something simple like std.algorithm.max() on an int or a float and invariably I end up just rewriting a max function for my specific type and marking it as pure nothrow. This is obviously a suboptimial solution. Since the source needs to be available anyhow for templates to be usable, my proposal would be for pure/nothrow functions to be able to call templated functions that are not marked as pure/nothrow as long as they would compile if marked pure/nothrow. Also, I think that we need to establish a strong convention, for objects, that opCmp, opEquals and a few other "standard" functions should always be const pure nothrow, and that it is acceptable for any library code (mixins, etc.) to assume this.Votes++; -- Simen
Nov 25 2009
dsimcha wrote:One issue that should ideally be resolved before D2 is finalized that I meant to bring up here a long time ago is how to handle pure and nothrow in generic functions. For example: T max(T)(T lhs, T rhs) { return (lhs > rhs) ? lhs : rhs; } Obviously, if T is an int, max can be pure nothrow. However, if T is some user defined type, then who knows? I've run into a few cases where I'm writing a pure function that needs to call something simple like std.algorithm.max() on an int or a float and invariably I end up just rewriting a max function for my specific type and marking it as pure nothrow. This is obviously a suboptimial solution. Since the source needs to be available anyhow for templates to be usable, my proposal would be for pure/nothrow functions to be able to call templated functions that are not marked as pure/nothrow as long as they would compile if marked pure/nothrow.That sounds reasonable to me. Already in many cases, the function body must be analysed in order to determine the return type, so it must also be analysed to determine its pure/nothrow-ness. Implementation might be tricky, though. Also, I think that we need to establish a strongconvention, for objects, that opCmp, opEquals and a few other "standard" functions should always be const pure nothrow, and that it is acceptable for any library code (mixins, etc.) to assume this.And what about safe ? BTW, it worries me a little that safe, pure, and ability to be used in CTFE are concepts which have about 90% overlap. Yet none is a subset of another.
Nov 25 2009
== Quote from Don (nospam nospam.com)'s articledsimcha wrote:I would say that safe doesn't make much sense. What if you're implementing your comparison function using memcmp() or something else that involves a bunch of pointers? If you pass memcmp() invalid parameters, it can segfault, and would therefore have to be marked as unsafe, meaning that safe functions couldn't call it.One issue that should ideally be resolved before D2 is finalized that I meant to bring up here a long time ago is how to handle pure and nothrow in generic functions. For example: T max(T)(T lhs, T rhs) { return (lhs > rhs) ? lhs : rhs; } Obviously, if T is an int, max can be pure nothrow. However, if T is some user defined type, then who knows? I've run into a few cases where I'm writing a pure function that needs to call something simple like std.algorithm.max() on an int or a float and invariably I end up just rewriting a max function for my specific type and marking it as pure nothrow. This is obviously a suboptimial solution. Since the source needs to be available anyhow for templates to be usable, my proposal would be for pure/nothrow functions to be able to call templated functions that are not marked as pure/nothrow as long as they would compile if marked pure/nothrow.That sounds reasonable to me. Already in many cases, the function body must be analysed in order to determine the return type, so it must also be analysed to determine its pure/nothrow-ness. Implementation might be tricky, though. Also, I think that we need to establish a strongconvention, for objects, that opCmp, opEquals and a few other "standard" functions should always be const pure nothrow, and that it is acceptable for any library code (mixins, etc.) to assume this.And what about safe ?
Nov 25 2009
dsimcha wrote:I would say that safe doesn't make much sense. What if you're implementing your comparison function using memcmp() or something else that involves a bunch of pointers? If you pass memcmp() invalid parameters, it can segfault, and would therefore have to be marked as unsafe, meaning that safe functions couldn't call it.A safe function is only safe if the parameters passed to it are valid. memcmp() cannot be safe as it does pointer arithmetic.
Nov 27 2009
== Quote from Walter Bright (newshound1 digitalmars.com)'s articledsimcha wrote:call it.I would say that safe doesn't make much sense. What if you're implementing your comparison function using memcmp() or something else that involves a bunch of pointers? If you pass memcmp() invalid parameters, it can segfault, and would therefore have to be marked as unsafe, meaning that safe functions couldn'tA safe function is only safe if the parameters passed to it are valid. memcmp() cannot be safe as it does pointer arithmetic.I think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.
Nov 27 2009
dsimcha wrote:== Quote from Walter Bright (newshound1 digitalmars.com)'s articleIt seems to me that one of the most important features of SafeD is that whenever a safe function invokes a function, it does so only with valid parameters. The problem with memcmp() is that the required relationship between the parameters is complicated, and can't be determined statically by the compiler. The fact that internally it does pointer arithmetic is a symptom of this problem: it might be accessing memory which is not implied by the parameters. So memcmp() cannot be trusted. Likewise, if it contains asm, it might be accessing non-parameter memory. OTOH, this contains pointer arithmetic but is perfectly fine: bool ptrcmp(char *x, char *y) { char *z = x+100; return y < z; }dsimcha wrote:call it.I would say that safe doesn't make much sense. What if you're implementing your comparison function using memcmp() or something else that involves a bunch of pointers? If you pass memcmp() invalid parameters, it can segfault, and would therefore have to be marked as unsafe, meaning that safe functions couldn'tA safe function is only safe if the parameters passed to it are valid. memcmp() cannot be safe as it does pointer arithmetic.I think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.
Nov 27 2009
Don wrote:It seems to me that one of the most important features of SafeD is that whenever a safe function invokes a function, it does so only with valid parameters. The problem with memcmp() is that the required relationship between the parameters is complicated, and can't be determined statically by the compiler. The fact that internally it does pointer arithmetic is a symptom of this problem: it might be accessing memory which is not implied by the parameters. So memcmp() cannot be trusted.Exactly. You said it better than me!
Nov 27 2009
dsimcha wrote:I think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there's no way that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.
Nov 27 2009
Hello Walter,there's no way that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp().I think that's backwards. There's no way memcmp can be sure it's arguments are safe just because it's being called from a safe function. OTOH, if a trusted function can do the needed checks, then so can a safe function. The problem is that there is is no way for DMD to check that it has; thus the trusted wrapper.
Nov 27 2009
Walter Bright wrote:dsimcha wrote:Hm, if we think of it, memcmp can be safe no problem. This is beacuse it oly reads stuff. There are three possible outcomes: a) valid addresses, all's fine b) incorrect addresses within the application, erroneous result returned c) incorrect addresses outside the application, segfault None of the above is unsafe. So memcmp is safe. (In contrast, memcpy is not). Color me surprised but convinced. AndreiI think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there's no way that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.
Nov 27 2009
Andrei Alexandrescu wrote:Walter Bright wrote:Although Walter had previously talked about making safe a little stronger than just memory safety -- with the goal of eliminating undefined behaviour. So (b) would be a problem. After all, you could you use the same argument to say that array bounds checking isn't required for reads, only for writes.dsimcha wrote:Hm, if we think of it, memcmp can be safe no problem. This is beacuse it oly reads stuff. There are three possible outcomes: a) valid addresses, all's fine b) incorrect addresses within the application, erroneous result returned c) incorrect addresses outside the application, segfault None of the above is unsafe. So memcmp is safe. (In contrast, memcpy is not). Color me surprised but convinced. AndreiI think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there's no way that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.
Nov 27 2009
== Quote from Don (nospam nospam.com)'s articleAndrei Alexandrescu wrote:Quick question about the eliminating undefined behavior thing: Isn't overflowing a signed int undefined behavior? If so, how would we eliminate undefined behavior without very expensive runtime checks?Walter Bright wrote:Although Walter had previously talked about making safe a little stronger than just memory safety -- with the goal of eliminating undefined behaviour. So (b) would be a problem. After all, you could you use the same argument to say that array bounds checking isn't required for reads, only for writes.dsimcha wrote:Hm, if we think of it, memcmp can be safe no problem. This is beacuse it oly reads stuff. There are three possible outcomes: a) valid addresses, all's fine b) incorrect addresses within the application, erroneous result returned c) incorrect addresses outside the application, segfault None of the above is unsafe. So memcmp is safe. (In contrast, memcpy is not). Color me surprised but convinced. AndreiI think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there's no way that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.
Nov 27 2009
On Sat, 28 Nov 2009 00:20:47 +0300, dsimcha <dsimcha yahoo.com> wrote:== Quote from Don (nospam nospam.com)'s articleI don't think integer overflow could be considered an undefined behavior. It's pretty much expected that uint.max + 1 == 0.Andrei Alexandrescu wrote:Quick question about the eliminating undefined behavior thing: Isn't overflowing a signed int undefined behavior? If so, how would we eliminate undefined behavior without very expensive runtime checks?Walter Bright wrote:passingdsimcha wrote:I think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior bynoincorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there'sreturnedway that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.Hm, if we think of it, memcmp can be safe no problem. This is beacuse it oly reads stuff. There are three possible outcomes: a) valid addresses, all's fine b) incorrect addresses within the application, erroneous resultc) incorrect addresses outside the application, segfault None of the above is unsafe. So memcmp is safe. (In contrast, memcpyisnot). Color me surprised but convinced. AndreiAlthough Walter had previously talked about making safe a little stronger than just memory safety -- with the goal of eliminating undefined behaviour. So (b) would be a problem. After all, you could you use the same argument to say that array bounds checking isn't required for reads, only for writes.
Nov 27 2009
Denis Koroskin:I don't think integer overflow could be considered an undefined behavior. It's pretty much expected that uint.max + 1 == 0.Computers are (mostly) deterministic, so in a certain sense everything they do can be expected :-) But sometimes the programmer "forgets" or doesn't take into account that a number can be int.max, so the overflow can be unexpected for him/her. The same can be said for array bounds, the expected that a write past the array end will give troubles, but having bound tests is often useful anyway, because it helps catch programming errors, etc. Bye, bearophile
Nov 27 2009
== Quote from Denis Koroskin (2korden gmail.com)'s articleOn Sat, 28 Nov 2009 00:20:47 +0300, dsimcha <dsimcha yahoo.com> wrote:What about int.max + 1? I specifically mentioned **signed** integers because, IIRC overflowing these is undefined in C, but overflowing unsigned is defined.== Quote from Don (nospam nospam.com)'s articleI don't think integer overflow could be considered an undefined behavior. It's pretty much expected that uint.max + 1 == 0.Andrei Alexandrescu wrote:Quick question about the eliminating undefined behavior thing: Isn't overflowing a signed int undefined behavior? If so, how would we eliminate undefined behavior without very expensive runtime checks?Walter Bright wrote:passingdsimcha wrote:I think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior bynoincorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there'sreturnedway that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.Hm, if we think of it, memcmp can be safe no problem. This is beacuse it oly reads stuff. There are three possible outcomes: a) valid addresses, all's fine b) incorrect addresses within the application, erroneous resultc) incorrect addresses outside the application, segfault None of the above is unsafe. So memcmp is safe. (In contrast, memcpyisnot). Color me surprised but convinced. AndreiAlthough Walter had previously talked about making safe a little stronger than just memory safety -- with the goal of eliminating undefined behaviour. So (b) would be a problem. After all, you could you use the same argument to say that array bounds checking isn't required for reads, only for writes.
Nov 27 2009
dsimcha wrote:What about int.max + 1? I specifically mentioned **signed** integers because, IIRC overflowing these is undefined in C, but overflowing unsigned is defined.It's undefined behavior in C because C supports ones-complement arithmetic. D does not - twos-complement only.
Nov 27 2009
dsimcha:Isn't overflowing a signed int undefined behavior?Yes, it can be.If so, how would we eliminate undefined behavior without very expensive runtime checks?<I have explained LLVM devs how to speed-up some of those runtime checks. Do you exactly know how much expensive they are, in synthetic benchmarks or activate those runtime tests, results are not conclusive). Do you prefer a less buggy program or a fast&buggy program? There are ways to infer and remove at compile time part of those tests (or sometimes pull them out of loops). Bye, bearophile
Nov 27 2009
dsimcha wrote:Quick question about the eliminating undefined behavior thing: Isn't overflowing a signed int undefined behavior?No. On every 2's complement machine I've ever heard of, the behavior is defined and the same.
Nov 27 2009
Don wrote:Andrei Alexandrescu wrote:I think it would be implementation-defined behavior - in case (b) memcmp would return an implementation-defined value but still defined.Walter Bright wrote:Although Walter had previously talked about making safe a little stronger than just memory safety -- with the goal of eliminating undefined behaviour. So (b) would be a problem.dsimcha wrote:Hm, if we think of it, memcmp can be safe no problem. This is beacuse it oly reads stuff. There are three possible outcomes: a) valid addresses, all's fine b) incorrect addresses within the application, erroneous result returned c) incorrect addresses outside the application, segfault None of the above is unsafe. So memcmp is safe. (In contrast, memcpy is not). Color me surprised but convinced. AndreiI think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there's no way that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.After all, you could you use the same argument to say that array bounds checking isn't required for reads, only for writes.Well less so. Reading an array element off-bounds that's of an elaborate type with indirections will lead to UB. Andrei
Nov 27 2009
Andrei Alexandrescu wrote:How could it?I think it would be implementation-defined behavior - in case (b) memcmp would return an implementation-defined value but still defined.b) incorrect addresses within the application, erroneous result returned
Nov 27 2009
Walter Bright wrote:Andrei Alexandrescu wrote:The value itself does not matter. The point is the behavior is not undefined. Undefined behavior = anything within the realm of physical possibility could happen. Implementation-defined behavior = the behavior depends on the implementation. In the memcmp case, the behavior is always defined to return an int or to never return (segfault). The value of the int for incorrect inputs is implementation dependent because it depends on the way data of various objects is laid out in memory. The fact that the definition is complex does not render it undefined. Let's not confuse undefined with implementation-defined. I am firmly convinced that memcmp never falls in the undefined behavior realm. The behavior is always defined. AndreiHow could it?I think it would be implementation-defined behavior - in case (b) memcmp would return an implementation-defined value but still defined.b) incorrect addresses within the application, erroneous result returned
Nov 27 2009
Andrei Alexandrescu wrote:Let's not confuse undefined with implementation-defined. I am firmly convinced that memcmp never falls in the undefined behavior realm. The behavior is always defined.Makes sense. But I'd still want to make it not safe, by using a more expansive definition of safe to include some implementation defined behaviors.
Nov 27 2009
Walter Bright wrote:Andrei Alexandrescu wrote:It's funny how we are trading places. Til now I was the stickler for safety. I agree with the noble spirit, but not with the lack of precision. To me the main attraction of safe is that it has a very clear definition. For example, that allows me to sleep at night in spite of ~=. You want to define safe more loosely and more judgement-call-ish depending on how you feel about various particular cases. I don't like that. First, it means that now safety becomes a subjective matter. People on the newsgroup can now argue forever about how various idioms should or shouldn't be safe. Bartosz is getting the debating equivalent of a Gatling gun because now he can credibly argue that ~= could be considered not safe. Finally, if you're in a bad mood because your shoes are too tight one day, something will not be safe that should be. All that I don't like at all. It's not science, not engineering, and not even design. It's just doing things by ear. We've spent literally the past few years trying to eliminate such things from D, so we shouldn't counter that with a completely subjective call. AndreiLet's not confuse undefined with implementation-defined. I am firmly convinced that memcmp never falls in the undefined behavior realm. The behavior is always defined.Makes sense. But I'd still want to make it not safe, by using a more expansive definition of safe to include some implementation defined behaviors.
Nov 27 2009
I have a feeling that the safeD thing is a bit premature. I'm only posting this because then I can link to this post next summer, when it's becoming clear that I was right. Because I'm such a nice guy I won't even save this link. :P Noone's ever tried this feature in real code that people actually get paid for writing, have they? And no, Phobos doesn't count until it's gotten more use of the kind that where you have a boss that decied if you get money or not. By 'get paid for writing' I mean exactly what any sane person with industry experince would mean.
Nov 27 2009
On Fri, 27 Nov 2009 23:51:44 +0300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Walter Bright wrote:Points 2 and 3 introduce undefined behavior, which is not allowed in SafeD :pdsimcha wrote:Hm, if we think of it, memcmp can be safe no problem. This is beacuse it oly reads stuff. There are three possible outcomes: a) valid addresses, all's fine b) incorrect addresses within the application, erroneous result returned c) incorrect addresses outside the application, segfault None of the above is unsafe. So memcmp is safe. (In contrast, memcpy is not). Color me surprised but convinced. AndreiI think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there's no way that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.
Nov 27 2009
Denis Koroskin wrote:On Fri, 27 Nov 2009 23:51:44 +0300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:s/undefined/implementation-defined/ AndreiWalter Bright wrote:Points 2 and 3 introduce undefined behavior, which is not allowed in SafeD :pdsimcha wrote:Hm, if we think of it, memcmp can be safe no problem. This is beacuse it oly reads stuff. There are three possible outcomes: a) valid addresses, all's fine b) incorrect addresses within the application, erroneous result returned c) incorrect addresses outside the application, segfault None of the above is unsafe. So memcmp is safe. (In contrast, memcpy is not). Color me surprised but convinced. AndreiI think you misunderstood the argument. memcmp() could be trusted if functions only need to be safe when passed valid parameters, though I don't necessarily agree that this makes sense. I was thinking memcmp() shouldn't even be marked trusted because it's so easy to invoke undefined behavior by passing incorrect parameters. This would mean that, if opCmp() uses it, opCmp() couldn't be marked as safe.memcmp() could be marked trusted, but it should not be. This is because trusted functions can be called by safe ones, but there's no way that an safe function can guarantee it sends memcmp() arguments that will work safely with memcmp(). Whoever calls memcmp() can be marked trusted.
Nov 27 2009
Andrei Alexandrescu wrote:Denis Koroskin wrote:Behavior is only implementation-defined if the implementation actually defines it. When targeting a specific implementation of a language, there is no difference between implementation-defined behavior and just plain defined behavior. I think the term you are looking for is "non-deterministic", which describes an operation which is defined to have one of several possible effects, but which of these effects actually takes place is not defined. Incidentally, it is sometimes possible to send output to a physical device by merely reading from a memory-mapped I/O address. Therefore the set of possible results of memcmp includes sending garbage output to a physical device. -- Rainer Deyke - rainerd eldwood.comPoints 2 and 3 introduce undefined behavior, which is not allowed in SafeD :ps/undefined/implementation-defined/
Nov 27 2009
Rainer Deyke wrote:Andrei Alexandrescu wrote:I only know of writing to cause actual device writing, so I'd be interested in a link that shows otherwise. Anyhow, this is a pretty good argument; reading some memory-mapped cache could cause other pages to be written etc. AndreiDenis Koroskin wrote:Behavior is only implementation-defined if the implementation actually defines it. When targeting a specific implementation of a language, there is no difference between implementation-defined behavior and just plain defined behavior. I think the term you are looking for is "non-deterministic", which describes an operation which is defined to have one of several possible effects, but which of these effects actually takes place is not defined. Incidentally, it is sometimes possible to send output to a physical device by merely reading from a memory-mapped I/O address. Therefore the set of possible results of memcmp includes sending garbage output to a physical device.Points 2 and 3 introduce undefined behavior, which is not allowed in SafeD :ps/undefined/implementation-defined/
Nov 30 2009