Live data from Hacker News

Giving C a superpower: custom header file (safe_c.h)

hwisnu.bearblog.dev

241–250 of 277 posts

Re: Giving C a superpower: custom header file (safe_c.h)

#241
post #239

Earlier quoted context omitted.

"Agentic driven OSes"? Sounds like AI hype babble.

Hype or not, that is what is being pushed https://www.windowscentral.com/microsoft/windows-11/microsof... https://www.klover.ai/apple-uses-ai-agents-10-ways-to-use-ai...

What does this have to do with system languages with manual memory management going away?

Re: Giving C a superpower: custom header file (safe_c.h)

#242

Earlier quoted context omitted.

How can anyone be this interested in maintaining an annex k implementation when it's widely regarded as a design failure, specially the global constraint handler. There's a reason why most C toolchains don't support it. https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm

FWIW, it's heavily used inside Microsoft and is actually pretty nice when combined with all the static analysis tools that are mandatory parts of the dev cycle.

AFAIK Microsoft's API is still a previous iteration not compliant with the standard annex K.

Re: Giving C a superpower: custom header file (safe_c.h)

#243
post #80

Earlier quoted context omitted.

No name mangling by default, far simpler toolchain, no dependence on libstdc++, compiles faster, usable with TCC/chibicc (i.e. much more amenable to custom tooling, be it at the level of a lexer, parser, or full compiler). C’s simplicity can be frustrating, but it’s an extremely hackable language thanks to that simplicity. Once you opt in to C++, even nominally, you lose that.

I highly doubt (and some quick checks seem to verify that) any of the tiny CC implementations will support the cleanup extension that most of this post's magic hinges upon. (Agree on your other points for what it's worth.)

TinyCC supports cleanup[1], onramp[2] supports C2y defer (which is a superset), slimcc[3] supports both.

[1] https://godbolt.org/z/hvj9vcncG

[2] https://github.com/ludocode/onramp

[3] https://github.com/fuhsnn/slimcc

Re: Giving C a superpower: custom header file (safe_c.h)

#244

Earlier quoted context omitted.

> You make some good, if oft-repeated, points They're oft repeated because they're real problems. > a plain Makefile works. > C has LSP support, like every other language. I haven't noticed C support in editors to be worse than other languages. Makefiles aren't supported well by clion or visual studio. LSP requires a compile-commands list to be able to work - which is a pita to export from makefiles. XCode and visual…

> Makefiles aren't supported well by clion or visual studio. I dunno what IDE support I might need - once the Makefile is written I'm not going to be constantly adding and removing packages on a frequent basis. As for IDE's, I am not using Clion, Visual Studio or XCode. Vim, Emacs and VSCode work fine with C projects, even when debugging interactively. > What would you say the downsides of writing a product in C in 2…

> As for IDE's, [...] Emacs and VSCode work fine with C projects, even when debugging interactively.

I'm pretty sure VSCode still needs a compile commands file to do proper syntax highlighting. Again, difficult and annoying to generate automatically with makefiles.

To be clear, I'm not saying you can't set it all up. I'm just saying the IDE experience writing C is worse - obviously worse - than the experience programming in other modern languages.

> I'll go slightly slower; this is not a significant enough factor to make anyone consider switching languages.

Well, I can disprove that right now. I'm anyone. And the poor velocity writing C is a big reason I don't use it. Its just so much work to do simple things - like validate a UTF8 string. Or make a resizable array. Or write a function which can return either a value or an error.

In C, I feel like I'm a human compiler doing a bunch of things I want my compiler to do for me. C is slower to write and easier to mess up compared to more modern languages like Zig or Rust.

I did a side by side test a few years ago, implementing the same program in a variety of languages. The C code was about 2x as large as the same program in typescript, but it ran much faster. It was also much harder to debug. Zig and Rust were half the size of my C code and just as performant!

I don't see any reason to spend more work to achieve the same - or a worse - result.

> C header files can be used to automatically perform the FFI for every single mainstream language.

Every single one? I roll to doubt. Does the javascript ecosystem parse C header files for FFI? Does Java? C#? Rust? I know LuaJIT and Zig do, but I'm not sure about any others.

If C headers were only used for FFI, I wouldn't mind them so much. But they're also needed within a C program. And the semantics are idiosyncratic and weird. Want to inline something? It probably has to go in the header file as a static method. Want a global? Declare it in the header as an extern, and put it in exactly 1 C file. Structs? Did you want to declare the whole type or make it opaque? Because those are different. Functions can have different type signatures in header files and C files, but only in certain ways. And so on. So many weird, stupid rules you need to learn.

And by the time you've done all that, you're almost certainly leaving performance on the table as a result of not compiling the whole program in a single codegen unit.

Its 2025. Why waste your limited time on this earth acting as a human compiler? The computer can do a way better job of it.

Re: Giving C a superpower: custom header file (safe_c.h)

#245
post #55

Earlier quoted context omitted.

It's only regarded as design failure by the linux folks. Maybe because it came from Microsoft, NIH syndrome. A global constraint handler is still by far better than dynamic env handlers, and most of the existing libc/POSIX design failures. You can disable this global constraint handler btw.

> Maybe because it came from Microsoft, NIH syndrome. No it is because you still need to get the size calculation correct, so it doesn't actually have any benefit over the strn... family other than being different. Also a memcpy that can fail at runtime, seems to be only complicating things. If anything it should fail at compile time.

If the optimizer cannot see the sizes, it has to defer the error to run-time. If it sees it (as with _FORTIFY_SOURCE=3) it fails at compile0-time already. The difference to _FORTIFY_SOURCE is that it guarantees to fail, whereas with _FORTIFY_SOURCE you never know.

Re: Giving C a superpower: custom header file (safe_c.h)

#246

Earlier quoted context omitted.

> Makefiles aren't supported well by clion or visual studio. I dunno what IDE support I might need - once the Makefile is written I'm not going to be constantly adding and removing packages on a frequent basis. As for IDE's, I am not using Clion, Visual Studio or XCode. Vim, Emacs and VSCode work fine with C projects, even when debugging interactively. > What would you say the downsides of writing a product in C in 2…

> As for IDE's, [...] Emacs and VSCode work fine with C projects, even when debugging interactively. I'm pretty sure VSCode still needs a compile commands file to do proper syntax highlighting. Again, difficult and annoying to generate automatically with makefiles. To be clear, I'm not saying you can't set it all up. I'm just saying the IDE experience writing C is worse - obviously worse - than the experience program…

> I'm pretty sure VSCode still needs a compile commands file to do proper syntax highlighting. Again, difficult and annoying to generate automatically with makefiles.

TBH, I can't remember when I set VSCode up, or even if I did (may have just used a plugin and called it a day). ISTR something about clang, but it all just works so I didn't go into it to maintain

> To be clear, I'm not saying you can't set it all up. I'm just saying the IDE experience writing C is worse - obviously worse - than the experience programming in other modern languages.

If it is worse than Go, Java or C# in VSCode, I honestly did not notice, having used VSCode with all those languages.

> I don't see any reason to spend more work to achieve the same - or a worse - result.

Thankfully, the extra effort is very small, so I don't care because the extra payoff is so large.

> Every single one? I roll to doubt. Does the javascript ecosystem parse C header files for FFI? Does Java? C#? Rust? I know LuaJIT and Zig do, but I'm not sure about any others.

Okay, maybe not every single one, but Javascript (Node.js) and Java are definitely supported in Swig. C# supports native calling by default anyway so no swig support necessary, and Rust already can FFI into C code.

So, from your list, everything is supported.

> Its 2025. Why waste your limited time on this earth acting as a human compiler?

I'm not acting as a human compiler. Missing some optional features doesn't make me a human compiler (what a strange take, though. You sound personally aggrieved that someone who has delivered using Java, C#, Go, Python and more can be productive in C with only a small difference in velocity).

More language features rarely translate into more successful products. The most successful products, in terms of deployment numbers, were built with the least exciting technologies - plain Java prior to 2015, etc.

Re: Giving C a superpower: custom header file (safe_c.h)

#247

Earlier quoted context omitted.

FWIW, it's heavily used inside Microsoft and is actually pretty nice when combined with all the static analysis tools that are mandatory parts of the dev cycle.

AFAIK Microsoft's API is still a previous iteration not compliant with the standard annex K.

## Microsoft Windows/MINGW_HAS_SECURE_API

* `fopen_s`, `freopen_s` deviate in the API: restrict is missing.

* `strtok_s`, `wcstok_s`,`vsnprintf_s` miss the dmax argument.

* `vsnprintf_s` adds a maxarg argument.

* `vswprintf` adds a maxarg argument on w32. (with `__STRICT_ANSI__` undefined)

* no `strnlen` on mingw32.

* no `errno_t` return type for `qsort_s`, only `void`.

* reversed argument order for `localtime_s` and `gmtime_s`.

* older mingw versions have `wchar.h` with only 2 functions: `wcscmp`, `wcslen`

* no `RSIZE_MAX`

* `memmove_s` does not clear dest with ERANGE when `count > dmax` and EINVAL when src is a NULL pointer.

* `vsprintf_s`, `sprintf_s` return `-1` on all errors, not just encoding errors. (Wrong standard)

* With `wcsrtombs` (used by `wcsrtomb_s`) the `retval` result includes the terminating zero, i.e. the result is `+1` from the spec.

`getenv_s` returns in len the size of the env buffer, not the len, as described in the standard (https://en.cppreference.com/w/c/program/getenv). The Microsoft size is len + 1. Their usage example is also wrong: https://learn.microsoft.com/en-us/cpp/c-runtime-library/refe...

Re: Giving C a superpower: custom header file (safe_c.h)

#248
post #149

Earlier quoted context omitted.

I consider code written in Frama-C as a verifiable C dialect, like SPARK is to Ada, rather than C proper. I find it funny how standard C is an undefined-behaviour minefield with few redeeming qualities, but it gets some of the best formal verification tools around.

IMHO and maybe counterintuitively, I do not think the existence of UB makes it harder to do formal verification or have safe C implementations. The reason is that you can treat it as an error if the program encounters UB, so one can either derive local requirements or add run-time checks (such as Fil-C) and then obtains spatial and temporal isolation of memory object.

[deleted]

Re: Giving C a superpower: custom header file (safe_c.h)

#249
post #245

Earlier quoted context omitted.

> Maybe because it came from Microsoft, NIH syndrome. No it is because you still need to get the size calculation correct, so it doesn't actually have any benefit over the strn... family other than being different. Also a memcpy that can fail at runtime, seems to be only complicating things. If anything it should fail at compile time.

If the optimizer cannot see the sizes, it has to defer the error to run-time. If it sees it (as with _FORTIFY_SOURCE=3) it fails at compile0-time already. The difference to _FORTIFY_SOURCE is that it guarantees to fail, whereas with _FORTIFY_SOURCE you never know.

In C I am responsible to tell the compiler where my arrays end. How is it supposed to know how many arrays there are in an allocation? Why should the compiler trust one expression about the size, but not the other? If I would want to limit memcpy by the size of the destination, I could write memcpy(dest, src, MAX(dest_size, ...)) instead, but I don't want that most of the time.

Re: Giving C a superpower: custom header file (safe_c.h)

#250
post #245

Earlier quoted context omitted.

If the optimizer cannot see the sizes, it has to defer the error to run-time. If it sees it (as with _FORTIFY_SOURCE=3) it fails at compile0-time already. The difference to _FORTIFY_SOURCE is that it guarantees to fail, whereas with _FORTIFY_SOURCE you never know.

In C I am responsible to tell the compiler where my arrays end. How is it supposed to know how many arrays there are in an allocation? Why should the compiler trust one expression about the size, but not the other? If I would want to limit memcpy by the size of the destination, I could write memcpy(dest, src, MAX(dest_size, ...)) instead, but I don't want that most of the time.

The compiler knows about the sizes by either statically allocated sizes (_FORTIFY_SOURCE=2, __builtin_object_size) or malloc'ed sizes (_FORTIFY_SOURCE=3, __builtin_dynamic_object_size). See e.g. https://developers.redhat.com/articles/2022/09/17/gccs-new-f...

Since the user is mostly wrong with memory bounds, the compiler checks it also. And with clang even allows user-defined warnings.

We all known that C programmers know it better, and hate bounds-checks, that's why there are so many out-of-bounds errors still.

Post reply on HN