3 ms·
Modern C for C++ Peeps (2019)
- rwmj 5y ago"Modern C" now effectively includes __attribute__((cleanup)), in as much as it's widely used by large free software projects and supported in both GCC and Clang.
- teddyh 5y agoDocumentation: “cleanup (cleanup_function) The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variables; it may not be applied to parameters or variables with static storage duration. The function must take one parameter, a pointer to a type compatible with the variable. The return value of the function (if any) is ignored. If -fexceptions is enabled, then cleanup_function is run during the stack unwinding that happens during the processing of the exception. Note that the cleanup attribute does not allow the exception to be caught, only to perform an action. It is undefined what happens if cleanup_function does not return normally.” — https://gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute https://gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/Common-Variabl...
- mrpippy 5y agoIs it widely used? I've only come across it in GLib (g_auto*), but even then it couldn't be used in GStreamer because they also support building with MSVC.
- fpoling 5y agosystemd code uses it widely.
- WalterBright 5y agoThis comes from the Scope Guard Statement in D, from an idea originally proposed by Andrei Alexandrescu and Petru Marginean. https://dlang.org/spec/statement.html#ScopeGuardStatement https://dlang.org/spec/statement.html#ScopeGuardStatement
- bsder 5y agoThat's just horrible. Why does the C committee keep wanting to make the language into C++? Is this something that rank and file programmers actually want? Is this something that library writers are demanding? At this point, I think I'm pretty fine with C anchoring down on features unless there is an absolutely pressing demand. There are enough newer languages experimenting in the space that I don't feel the need to pollute C with this stuff until those languages hash it all out.
- adrianN 5y agoRAII is one of the best things about C++. It makes cleanup much simpler than what you need to do without being able to bind cleanup code to scopes. You avoid the kind of complexity that can lead to "goto fail" style problems.
- bsder 5y agoIf you want RAII, then use C++--no one is stopping you. A lot of embedded developers STRONGLY disagree with you. There is a reason why embedded developers tend to turn off a whole bunch of C++ features. Note all the: "No RTTI. No templates. No exceptions." flags that embedded folks always engage. Now that VSCode is getting actual support for embedded (see all the work the Rust Embedded guys did, for example) as well as official ARM support (Eclipse Theia), various languages can be used for development. Thanks to this, people no longer need to force things because "If it's not in the C toolchain, nobody will support it." People don't need to torture C anymore to use their favorite language feature on their hardware of choice.
- adrianN 5y agoThanks, I did safety critical embedded development for while, in C++. We did turn off a bunch of features of course. We never heap-alloced for example. But destructors were used extensively to make sure that important actions happened during error conditions. We were lucky to be able to use C++ because we had a compiler for our target platform. Not every target has a C++ compiler, so I think adding something as useful as scope-bound cleanup to C makes perfect sense.
- klaussilveira 5y agoSomewhat relevant: https://250bpm.com/blog:4/ https://250bpm.com/blog:4/
- bierjunge 5y agoNice intro, but it's very vague and not nearly a complete overview. There is a good book written by Jens Gustedt [0] which is a great guide for C with all the new stuff. The book itself is CC licensed and code examples are MIT licensed. Jens is one of the good guys. [0] https://modernc.gforge.inria.fr/ https://modernc.gforge.inria.fr/
- bluetomcat 5y ago> Wrap your structs in a typedef I tend to disagree. Unless you are providing an API for third-party use and want to make your data types opaque to callers, do not ever use typedef with structs and pointers. A declaration like "struct foo *f" tells you two things - f itself is a pointer, and the pointed-to value is not a scalar (i.e. has named members). The "_t" suffix idiom is predominantly used by the standard library for integral scalars with certain properties and semantics, e.g. pid_t, uid_t, gid_t, time_t.
- visualradio 5y agoIf programmers do want to wrap structs in a typedef without using the "_t" suffix, the Vulkan API appears to have settled on upper-camel case: typedef struct VkMemoryBarrier { VkStructureType sType; const void* pNext; VkAccessFlags srcAccessMask; VkAccessFlags dstAccessMask; } VkMemoryBarrier;
- jimbob45 5y agoAgreed. If you typedef your struct, I can’t know if you wrapped it in a weird macro or if your data type is actually a renamed primitive. Once I gain familiarity with your codebase, it won’t matter, but it otherwise unnecessarily raises the barrier of entry. That said, typedefs/macros may be essential for portability concerns.
- Gibbon1 5y ago> can’t know if you wrapped it in a weird macro The solution to that problem is don't do that.
- ynfnehf 5y agoThe _t suffix is also reserved by posix. (And by the C standard if the name starts with int or unit.) I agree with just using struct foo, as does the Linux style guide. (Edit: I just noticed the page mentions this, but it is perhaps useful to reiterate.)
- 5y ago
- giomasce 5y agoI don't really understand why RAII is related to many small memory allocations. Is memory leaking less of a problem if it is in just a few big allocations? The proposed solution of using handles instead of pointers is a tradeoff that can make a lot of sense in some situations (it basically trades slower access to objects for better safety and defensive programming), but it is rather independent of RAII. Handles or not radically different from pointers: they still need an allocator (and you can say that your custom one is better tailored to your problem, but writing an allocator is not easy, and it's all to be seen if yours is better than the standard ones) and you still need to remember to invalidate handles, which is what RAII is really for. So using handles can be a good idea, both in C and in C++, but it's really orthogonal to RAII. It can partially compoensate the lack of copy constructors and destructors, but if you need to keep a reference count to a handle you're still short of a good solution, and your code must be ready at any place to cope with a expired handle.