TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Defer Reference Implementation for C

77 点作者 cyber1超过 4 年前

10 条评论

dgellow超过 4 年前
In case someone wants the same in C++, the Guidelines Support Library comes with the class &quot;final_action&quot; and the function &quot;finally()&quot;.<p>Check the implementation here: <a href="https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;GSL&#x2F;blob&#x2F;master&#x2F;include&#x2F;gsl&#x2F;gsl_util#L76" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;GSL&#x2F;blob&#x2F;master&#x2F;include&#x2F;gsl&#x2F;gsl...</a>.<p>Example from <a href="https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;cpp&#x2F;code-quality&#x2F;c26448?view=vs-2019" rel="nofollow">https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;cpp&#x2F;code-quality&#x2F;c26448?vie...</a>:<p><pre><code> void poll(connection_info info) { connection c = {}; if (!c.open(info)) return; auto end = gsl::finally([&amp;c] { c.close(); }); while (c.wait()) { connection::header h{}; connection::signature s{}; if (!c.read_header(h)) return; if (!c.read_signature(s)) return; &#x2F;&#x2F; ... } } </code></pre> I love this pattern, it&#x27;s a very nice way to have a kind of RAII but with more control and flexibility.
rwmj超过 4 年前
So much complexity. Just standardize __attribute__((cleanup)) which is already being used by a load of software, is available already in GCC and Clang, and does everything that anyone wants.
neostrauss超过 4 年前
Presumably GCC (and I believe Clang)&#x27;s __cleanup__ attribute provides this functionality already in most cases?<p>Any platform where Clang and GCC aren&#x27;t supported is a platform where this style of code shouldn&#x27;t be used, no?
评论 #24646015 未加载
augustk超过 4 年前
If I&#x27;m not mistaken, the first example is equivalent to the following purely structured code:<p><pre><code> void * const p = malloc(25); if (p != NULL) { void * const q = malloc(25); if (q != NULL) { if (mtx_lock(&amp;mut) != thrd_error) { mtx_unlock(&amp;mut); } free(q); } free(p); } </code></pre> At least to me, this flow is much easier to understand.
评论 #24649275 未加载
评论 #24649476 未加载
jzelinskie超过 4 年前
I see this idea posted with some frequency and the responses are almost always &quot;clang and gcc have compiler intrinsics for this&quot;. I&#x27;m not a regular C programmer, so this begs the question: why is it that nobody seems to know or use them?
评论 #24651038 未加载
评论 #24648554 未加载
评论 #24649443 未加载
评论 #24648481 未加载
saagarjha超过 4 年前
I hate commenting on this usually, but please please please don&#x27;t touch letter-spacing if you want people to be able to read your text! Doubly so if these are literally <i>headers</i> and using a fairly ugly, squat font…
评论 #24644436 未加载
评论 #24644636 未加载
ludocode超过 4 年前
Is this a serious proposal for a new C language feature? Or is this just an experiment from someone&#x27;s masters thesis or something? The paper is titled &quot;Proposal for C2x&quot;, but this can&#x27;t possibly be seriously considered. I have so many questions.<p>In section 1.1, the linearization it gives with goto statements is barely longer than the defer example. They claim defer is better just because of the proximity of the cleanup code? Why not just move the &quot;resources acquired&quot; code to a separate function? You wouldn&#x27;t even need goto in that case, you could just nest if statements to do the cleanup.<p>The spec claims defer allocates memory. Why? As far as I know __attribute__((cleanup(fn))) doesn&#x27;t allocate memory. This defer may exhaust memory, and if so, it will immediately terminate execution of the enclosing guard block with a panic() and DEFER_ENOMEM. So like an exception?<p>This says exit() or panic() will clean up all guarded blocks across all function calls of the same thread. So basically stack unwinding? Apparently you can recover somewhere with a call to recover()? This is just exceptions by another name. This stack unwinding can&#x27;t possibly interoperate with existing code that expects error return values.<p>This claims it&#x27;s robust because any deferred statement is guaranteed to be executed eventually, and it describes in great detail how it runs defer statements on signals. What if I write an infinite loop, or get a SIGKILL, or yank the power cord? Obviously deferred statements won&#x27;t be executed.<p>This says defer is implemented with longjmp. Isn&#x27;t setjmp&#x2F;longjmp way too slow for exception handling? C++ compilers haven&#x27;t done exceptions that way for decades. What happens if I longjmp or goto past a defer statement? This says it just doesn&#x27;t invoke the defer mechanism and may result in memory leaks or other damage. Does that mean it&#x27;s undefined behaviour? C++ won&#x27;t compile a goto past constructors for good reason.<p>All POSIX error and signal codes have an equivalent prefixed with DEFER_, e.g. DEFER_ENOMEM, DEFER_HUP. This is just in case the system doesn&#x27;t already have ENOMEM? Doesn&#x27;t the standard already require that ENOMEM exist? If not, why not just make this feature require that ENOMEM exist? Why depend so much on errno for new core language features when it&#x27;s basically an ugly artifact of ancient C library functions?<p>&gt; If C will be extended with lamdas (hopefully in a nearer future)<p>I wouldn&#x27;t hold my breath.
评论 #24648694 未加载
andrepd超过 4 年前
Why is this better than RAII with a destructor&#x2F;drop being called whenever the block is exited? Also, this mechanism is already present in C via __attribute__(cleanup).
评论 #24645857 未加载
dnautics超过 4 年前
thing is, you&#x27;ll still want errdefer.
评论 #24645526 未加载
jart超过 4 年前
The C language shouldn&#x27;t need a defer statement keyword, because it&#x27;s so trivial to implement using an asm() macro that overwrites the return address.<p>Using a macro is more succinct:<p><pre><code> const char *s = gc(xasprintf(&quot;%s&#x2F;%s&quot;, dir, name)); </code></pre> Than what&#x27;s being proposed:<p><pre><code> char *s = xasprintf(&quot;%s&#x2F;%s&quot;, dir, name); defer free(s); </code></pre> See this x86 reference implementation of defer() and gc(). <a href="https:&#x2F;&#x2F;gist.github.com&#x2F;jart&#x2F;aed0fd7a7fa68385d19e76a63db687ff" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;jart&#x2F;aed0fd7a7fa68385d19e76a63db687f...</a> That should just work with GCC and Clang. That code is originally from the Cosmopolitan C Library (<a href="https:&#x2F;&#x2F;github.com&#x2F;jart&#x2F;cosmopolitan" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;jart&#x2F;cosmopolitan</a>) so check it out if you like the Gist and want more!<p>Please note the macro operates at function call boundaries rather than block scoped. I consider that a feature since it behaves sort of like a memory pool. Having side effects at the block scope level requires changing compilers, the language itself, and it would cause several important gcc optimization passes to be disabled in places where it&#x27;s used.
评论 #24646031 未加载
评论 #24644798 未加载
评论 #24644413 未加载
评论 #24644871 未加载
评论 #24644937 未加载
评论 #24644580 未加载
评论 #24649447 未加载
评论 #24644806 未加载
评论 #24644476 未加载