Live data from Hacker News

Tell HN: C Experts Panel – Ask us anything about C

news.ycombinator.com

361–370 of 978 posts

Re: Tell HN: C Experts Panel – Ask us anything about C

#361

Earlier quoted context omitted.

Just going to inject that this impacts a bunch of random optimizations and benchmarks. Just to fabricate an example: for (int i = 0; i Reasonably common idea but the compiler is allowed to assume the loop terminates precisely because signed overflow is undefined. I’m not trying to argue that signed overflow is the right tool for the job here for expressing ideas like “this loop will terminate”, but making signed over…

The compiler assumes that the loop will alwasy terminate and that assumption is wrong, because in reality there is the possibility that the loop will not terminate, since the hardware WILL overflow. So it's not the best solution. If we want to make this behaviour for optimizations (that are to me not worthed, giving the risk of potentially critical bugs) we must make that behavior explicit, not implicit: thus is the…

> The compiler assumes that the loop will alwasy terminate and that assumption is wrong, because in reality there is the possibility that the loop will not terminate, since the hardware WILL overflow.

The language is not a model of hardware, nor should it be. If you want to write to the hardware, the only option continues to be assembly.

Re: Tell HN: C Experts Panel – Ask us anything about C

#362
post #163

Earlier quoted context omitted.

Another approach would be a standard library of arithmetic routines that signal overflow. If people used them while parsing binary inputs that would prevent a lot of security bugs. The fact that this question exists and is full of wrong answers suggests a language solution is needed: https://stackoverflow.com/questions/1815367/catch-and-comput...

You can enable this in GCC on a compilation unit basis with `-fsanitize=signed-integer-overflow`. In combination with `-fsanitize-undefined-trap-on-error`, the checks are quite cheap (on x86, usually just a `jo` to a `ud2` instruction). (Note that while `-ftrapv` would seem equivalent, I've found it to be less reliable, particularly with compile-time checking.)

And clang!

Re: Tell HN: C Experts Panel – Ask us anything about C

#363
post #269

This is a subjective question. From the array of tools in your belt, when do you personally/professionally reach for C, or maybe more interestingly, when do you not reach for C?

Since I do almost all my software development in a Unix environment, usually I check the toolbox to see if there is already a program that has nearly the functionality I want, and if so then I cobble together a shell script. Sometimes (as with the Sudoku solver) it will be necessary to build a new component, and for that I usually use C since I am comfortable and experienced with it. (Also, if coded in Standard C, odds are that I can install it on whatever platform I need, with little or no adaptation.)

Re: Tell HN: C Experts Panel – Ask us anything about C

#364

Earlier quoted context omitted.

Wait, doesn't this mean that the BSD sockets API is inherently dependent on UB, casing different socket types to each other and sometimes only using the first few members, or am I misunderstanding you?

Yes and no. The thing I am describing is when you link a compilation unit using: struct internal_state { int dummy; } state; with another compilation unit that defined the same state differently: struct internal_state { int actual_meaningful_member_1; unsigned long actual_meaningful_member_2; } state; As far as I know, BSD socked do not do this. Zlib was doing this ( https://github.com/pascal-cuoq/zlib-fork/blob/a52f…

BSD sockets are weird in that the first struct's (sockaddr) size wasn't big enough, so APIs all take a nominal pointer to sockaddr but may require larger storage (sockaddr_storage) depending on the actual address.

  /*
   * Structure used by kernel to store most
   * addresses.
   */
  struct sockaddr {
          unsigned char   sa_len;         /* total length */
          sa_family_t     sa_family;      /* address family */
          char            sa_data[14];    /* actually longer; address value */
  };


  /*
   * RFC 2553: protocol-independent placeholder for socket addresses
   */
  #define _SS_MAXSIZE     128U
  #define _SS_ALIGNSIZE   (sizeof(__int64_t))
  #define _SS_PAD1SIZE    (_SS_ALIGNSIZE - sizeof(unsigned char) - \
                              sizeof(sa_family_t))
  #define _SS_PAD2SIZE    (_SS_MAXSIZE - sizeof(unsigned char) - \
                              sizeof(sa_family_t) - _SS_PAD1SIZE - _SS_ALIGNSIZE)
  
  struct sockaddr_storage {
          unsigned char   ss_len;         /* address length */
          sa_family_t     ss_family;      /* address family */
          char            __ss_pad1[_SS_PAD1SIZE];
          __int64_t       __ss_align;     /* force desired struct alignment */
          char            __ss_pad2[_SS_PAD2SIZE];
  };

Re: Tell HN: C Experts Panel – Ask us anything about C

#365
post #231
post #184

A lot C programmers prefer to keep structures within the C source file ("module"), as a poor man's encapsulation. For example: component.h: struct obj; typedef struct obj obj_t; obj_t *obj_create(void); // .. the rest of the API component.c: struct obj { int status; // .. whatever else }; obj_t * obj_create(void) { return calloc(1, sizeof(obj_t)); } However, as the component grows in complexity, it often becomes nece…

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.

ELF is very much not part of the C standard.

Re: Tell HN: C Experts Panel – Ask us anything about C

#367
post #223

Earlier quoted context omitted.

I think we are always looking at ways to "clean up C" but that this has to be done very carefully not to break existing code. For example, the committee recently voted to remove support for function definitions with identifier lists from C2x http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2432.pdf At least one vendor was not very happy with this decision. Undefined behaviors tend to be undefined for a reason and sho…

Does it concern you how aggressively compiler teams are exploiting UB?

I would say that there is a lot of concern in the committee about how compilers are optimizing based on pointer providence. There has been a study group looking at this. It now appears that they are likely to publish their proposal as a Technical Report.

Re: Tell HN: C Experts Panel – Ask us anything about C

#368

As there are a lot of C-masters lurking in this thread: How can one process unicode (UTF-8) properly in C? As a CJK person, I wish there was a robust solution. Are there any standardized ways or proposals? (Using wchar doesn't count.)

UTF-8 encoding works "as is" based on byte strings (char[]). The latest versions of the draft standard provide somewhat more support. I recommend heading toward a future where only UTF-8 encoding is used for multibyte characters and UCS-2 or similar for wchar_t. There is no need to support several different encodings.

UCS-2 is a bad choice -- it fails to represent most unicode characters. If you meant UTF-16, that's also a bad choice, because UTF-16 is also a variable width encoding, forcing programmers to use a some for of "extra-wide char".

I'm of the opinion that wchar_t should become an alias for char32_t.

Re: Tell HN: C Experts Panel – Ask us anything about C

#369
post #311

Earlier quoted context omitted.

Fat pointers in C would involve an ABI break for existing code, in that uintptr_t and uintmax_t would probably need to double in size.

It would presumably involve a new type that didn't exist in the current ABI. Those pointers would stay the same, and the new (twice as big) pointers would be used for the array feature.

The point of uintptr_t is that it's an integer type to which any pointer type can be cast. If you introduce a new class of pointers which are not compatible with uintptr_t, then suddenly you have pointers which are not pointers.

Re: Tell HN: C Experts Panel – Ask us anything about C

#370
post #223

Earlier quoted context omitted.

I think we are always looking at ways to "clean up C" but that this has to be done very carefully not to break existing code. For example, the committee recently voted to remove support for function definitions with identifier lists from C2x http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2432.pdf At least one vendor was not very happy with this decision. Undefined behaviors tend to be undefined for a reason and sho…

Does it concern you how aggressively compiler teams are exploiting UB?

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.

Post reply on HN