HNHacker News
TopNewBestAskShowJobs

msebor

117 karma · joined April 13, 2020

submissionscomments
msebor··on Tell HN: C Experts Panel – Ask us anything about C
I'm not aware of recent proposals for those but we have discussed ideas along those lines (closures: N2030, C++ lambdas, Apple Blocks: N1451, and I think there was one from Cilk). I think there was interest but not enough support for the details and likely also concerns from implementers.
msebor··on Tell HN: C Experts Panel – Ask us anything about C
I'd expect a proposal for (1) to be well received. The only proposal I recall that deals with (2) is http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2067.pdf. I think it's still being discussed. (3) is highly unlikely if it involved ABI changes. Even if it could be done without such changes unless there is a precedent for it in an existing compiler (and preferably more), it would likely be a tough sell.
msebor··on Tell HN: C Experts Panel – Ask us anything about C
WG14 in general looks favorably at proposals to align C more closely with C++ (within the overall spirit of the language) and I'd expect (1) would viewed in that light.

I'd also say there is consensus that (2) would be beneficial. There are some good ideas in http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2067.pdf although I don't think repurposing the register keyword for it was very popular. Not just because it wouldn't be compatible with C++ which deprecated register some time ago, but also because it's novel with no implementation or user experience behind it. My impression that this is waiting for a new proposal.

msebor··on Tell HN: C Experts Panel – Ask us anything about C
Several of us discussed typeof and I'd expect a proposal for a feature along these lines to be well received. (I recall someone even saying they're working on one but that shouldn't stop anyone from submitting one of their own.)
msebor··on Tell HN: C Experts Panel – Ask us anything about C
There are many improved versions of string APIs out there, too many in fact to choose from, and most suffer from one flaw or another, depending on one's point of view. Most of my recent proposals to incorporate some that do solve some of the most glaring problems and that have been widely available for a decade or more and are even parts of other standards (POSIX) have been rejected by the committee. I think only memccpy and strdup and strdndup were added for C2X. (See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2349.htm for an overview.)
msebor··on Tell HN: C Experts Panel – Ask us anything about C
C17 doesn't look much different than C89. If you are used to K&R C there may be some adjustment but I would expect it to be manageable.

What might perhaps be more challenging is adjusting to the changes in compilers. They tend to optimize code more aggressively and so writing code that closely follows the rules of the language (rather than making assumptions about the underlying hardware, even valid ones) is more important today than it was back in the 80's.

msebor··on Tell HN: C Experts Panel – Ask us anything about C
First, there needs to be a proposal for adding a feature (I'm not aware of one having been submitted recently). Second, any non-trivial proposed feature needs to have some existing user experience behind it. For libraries that typically means implementations shipping with operating systems or compilers (but successful third party libraries might also be considered). Finally, it also needs to appeal to people on the committee; that can be quite challenging as well. Many proposals that meet the first two criteria die because they simply don't get enough support within the committee.
msebor··on Tell HN: C Experts Panel – Ask us anything about C
memcpy and memmove aren't special. The part that discusses the copying of allocated objects is 6.5, p6, quoted below:

The effective type of an object for an access to its stored value is the declared type of the object, if any. If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is opied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.

msebor··on Tell HN: C Experts Panel – Ask us anything about C
This is a good example. Let me flesh it out a bit more to illustrate a specific instance of this problem:

  int a[2][2];
  int f (int i, int j)
   {
       int t = a[1][j];
       a[0][i] = 0;          // cannot change a[1]
       return a[1][j] - t;   // can be folded to zero
   }
The language says that elements of the matrix a must only be accessed by indices that are valid for each bound, so compilers can and some do optimize code based on that requirement (see https://godbolt.org/z/spSF8e).

But when a program breaks that requirement (say, by calling f(2, 0)) the function will likely return an unexpected value.

msebor··on Tell HN: C Experts Panel – Ask us anything about C
This is a common misconception (or poor way of phrasing it, sorry). Compiler implementers don't go looking for instances of undefined behavior in a program with the goal of optimizing it in some way. There is little value in optimizing invalid code. The opposite is the case.

But we must write code that relies on the same rules and requirements that programs are held to (and vice versa). When either party breaks those rules, either accidentally or deliberately, bad things happen.

What sometimes happens is that code written years or decades ago relies on the absence of an explicit guarantee in the language suddenly stops working because a compiler change depends on the assumption that code doesn't rely on the absence of the guarantee. That can happen as a result of improving optimizations, which is often but not not necessarily always motivated by improving the efficiency of programs. Better analysis can also help find bugs in code or avoid issuing warnings for safe code.

msebor··on Tell HN: C Experts Panel – Ask us anything about C
An object of any type, initialized or not, can be read by an lvalue of unsigned char (or any character type). That lets functions like memcpy (either the standard one or a hand-rolled loop) copy arbitrary chunks of memory.

There's some debate about the effects of reading an uninitialized local variable of unsigned char (like whether the same value must be read each time, or whether it's okay for each read to yield a different value).

This special exemption doesn't extend to any other types, regardless of whether or not they have padding bits or trap representations that could cause the read to trap. Few types do, yet the behavior of uninitialized reads in existing implementations is demonstrably undefined (inconsistent or contradictory to invariants expressed in the code of a test case), so any subtleties one might derive from the text of the standard must be viewed in that light.

msebor··on Tell HN: C Experts Panel – Ask us anything about C
Yes, it's undefined. It involves a read of an uninitialized local variable. Except for the special case of unsigned char, any uninitialized read is undefined.
msebor··on Tell HN: C Experts Panel – Ask us anything about C
Most of us on the committee would like to see more participation from other experts. The committee's mailing list should be open even to non-members. Attendance by non-members at meetings might require an informal invitation (I imagine a heads up to the convener should do it).
msebor··on Tell HN: C Experts Panel – Ask us anything about C
Casting between the three character types is safe and doesn't violate aliasing rules. In addition, objects of all types can be accessed by lvalues of any of the three character types (though unsigned char is recommended), so there's no problem there either.

I/O functions that take a plain char* are designed to interoperate with char arrays and strings, so passing in unsigned or signed char is a sign that they aren't being used as intended. (Functions that traffic in binary data like fread/fwrite should take void*).

msebor··on Tell HN: C Experts Panel – Ask us anything about C
Yes, both :) There are a few in public domain that might be helpful to experiment with. Clang has had a static analyzer for a while and GCC 10 adds one as well (and the maintainer is looking for help with implementing checkers so that's a good way to gain experience with writing one).
msebor··on Tell HN: C Experts Panel – Ask us anything about C
Robert's upcoming book has a survey of a few popular IDEs.
msebor··on Tell HN: C Experts Panel – Ask us anything about C
The ELF visibility attributes solve the part of the problem at the binary level (by hiding private library APIs from the application). The rest should be doable by structuring the project sources and headers in a suitable way.
msebor··on Tell HN: C Experts Panel – Ask us anything about C
The committee has reviewed a proposal (document N2360) to for const-correct string functions.

But making function signatures const-correct solves only a small part of the problem. A new API can only be used in new code, and casts can remove the constness from pointers leaving open the possibility that poorly written code will inadvertently change the const object. An attempt to change a global variable declared const will in all likelihood crash, but changing a local const can cause much more subtle bugs.

In my view, a more complete solution must include improving the detection of these types bugs in compilers and other static and even dynamic analyzers even without requiring code changes. It's not any more difficult to do that detecting out of bounds accesses. (In full generality it cannot be done just by relying on const; some other annotation is necessary to specify that a function that takes a const pointer doesn't cast the constness away and modify the object regardless.)

msebor··on Tell HN: C Experts Panel – Ask us anything about C
The C charter and the C committee's job is to standardize existing practice. That means codifying features that emerge as successful in multiple implementations (compilers or libraries), and that are in the overall spirit of the language.
msebor··on Tell HN: C Experts Panel – Ask us anything about C
Some implementations have been making a lot of effort to do just that. GCC in particular has been adding these types of checks (either as warnings or sanitizers) in recent years and although there is still much to improve I'd like to think we have made good progress.

Adding a rule requiring implementations to error out in cases of undefined behavior would be hard to specify in the standard. It could (and in my view should) be done by providing non-normative encouragement as "Recommended Practice."

msebor··on Tell HN: C Experts Panel – Ask us anything about C
There are "projects" underway to clean up the spec where it's viewed as either buggy, inconsistent, or underspecified. The atomics and threads sections are a coupled of example.

There are efforts to define the behavior in cases where implementations have converged or died out (e.g., twos complement, shifting into the sign bit).

There have been no proposals to add new array types and it doesn't seem likely at the core language level. C's charter is to standardize existing practice (as opposed to invent new features), and no such feature has emerged in practice. Same for modules. (C++ takes a very different approach.)

msebor··on Tell HN: C Experts Panel – Ask us anything about C
Some instances of undefined behavior at translation time can effectively be avoided in practice by tightening up requirements on implementations to diagnose them. But strictly speaking, because the standard allows compilers to continue to chug along even after an error and emit object code with arbitrary semantics, turning even such straightforward instances into constraint violations (i.e., diagnosable errors) doesn't prevent UB.

It might seem like defining the semantics for signed overflow would be helpful but it turns out it's not, either from a security view or for efficiency. In general, defining the behavior in cases that commonly harbor bugs is not necessarily a good way to fix them.

msebor··on Tell HN: C Experts Panel – Ask us anything about C
That doesn't seem likely. There have been no proposals for anything like it and there is a general resistance to subsetting either C or C++ (the exception being making support for new features optional).
msebor··on Tell HN: C Experts Panel – Ask us anything about C
Fixing minor bugs or inconsistencies and reducing the number and kinds of instances of undefined behavior are some of the efforts keeping the C committee busy.

Reviewing proposals to incorporate features supported by common implementations is another.

Aligning with other standards (e.g., floating point) and improving compatibility with others (C++) is yet another.

In general, when an ISO standard is done it essentially becomes dead. So for the C standard to continue to be active (on ISO's books) it needs to evolve.