Hacker News new | past | comments | ask | show | jobs | submit login

For [1] I would say that when the compiler does not control the standard library (e.g. most linux systems) then the compiler should treat qsort like any normal non-libc function call, it shouldn't be able to detect that I might be relying on implementation-specific guarantees. From a libc perspective, I would probably have a safe version of qsort used either on request or when NDEBUG is undefined, in which the implementation must either detect the inconsistency and abort in an implementation-defined matter, or select an ordering such that a<b in the ordering implies the existence of a finite chain a<x_1<x_2<...<x_n<b of comparison results in which each x_i is the equivalence class where the compare function said two entries were equal. I think that should be consistent with most sorting algorithms. (Whether the normal qsort should be the same as the safe version would only be needed if there were a significant-enough performance improvement.)

For [2] I disagree for two reasons. For one, merely having an answer at all, rather than entering an undefined behavior is valuable; having x+y=pseudorand(x,y) would still be better than complete UB because the damage that can be done is limited. The other reason is that addition/subtraction/multiplication does actually work modulo 2^n, so if I write e.g. (a+b-c) where b can be large but b-c is known to be small, it works even if the language is technically left-associative and having the a+b first is UB.

I pretty much agree with your point that the main problem is there is no way to work around UB; if there were a workaround there would be much less reason to complain. I would go a bit further and say such a workaround needs to be in the code itself to be effective, not merely a command line arg like fwrapv, so that it gets kept around when doing header inlining, LTO, copy-pasting code to other projects, etc.




> For [1] I would say that when the compiler does not control the standard library (e.g. most linux systems) then the compiler should treat qsort like any normal non-libc function call, it shouldn't be able to detect that I might be relying on implementation-specific guarantees.

I am guessing, for example, that you are not aware that every compiler will optimize `printf("Hello, world!\n");` to `puts("Hello, world!\n");`. memcpy and memset are even more heavily-optimized function calls by the compiler: for example, they don't prevent memory-to-register promotion.


I am aware of these things, the rant by Ulrich Drepper on this breaking glibc guarantees [0] explicitly what I had in mind when writing that.

[0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25609


> I pretty much agree with your point that the main problem is there is no way to work around UB; if there were a workaround there would be much less reason to complain.

There is a canonical workaround - cast operands to unsigned integer, do the operation, cast it back to signed integer. Overflow during casting to signed is implementation-defined behavior instead of UB.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: