# C goto vs Zig defer / errdefer / break

**URL:** <https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952>\
**Category:** Brainstorming\
**Tags:** language, c\
**Created:** [January 20, 2024, 11:00am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952 "2024-01-20T11:00:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 20, 2024, 11:00am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/1 "2024-01-20T11:00:14Z")

</div>

> [@The linux kernel community is discussing convert the linux kernel from c to modern c++](https://ziggit.dev/t/the-linux-kernel-community-is-discussing-convert-the-linux-kernel-from-c-to-modern-c/2824/14):
>
> Take the ‘defer’ or ‘errdefer,’ for example;

To be honest, I personally consider `goto` approach to cleanup code  
to be very nice, simple and readable. But this is the **only case**  
where explicit `goto` is really needed.

Zig’s way to do cleanup in a function requires [a bit more thinking](https://ziggit.dev/t/managing-file-reading-closing-buffer-allocation-and-deallocation/2389/10),  
whereas in C I do it automatically.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 20, 2024, 11:24am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/2 "2024-01-20T11:24:23Z")

</div>

> [@The linux kernel community is discussing convert the linux kernel from c to modern c++](https://ziggit.dev/t/the-linux-kernel-community-is-discussing-convert-the-linux-kernel-from-c-to-modern-c/2824/15):
>
> Write a small, non-trivial utility / program, that does something similar to a utility written in C

Once upon a time I’ve written [a file compressor](https://encode.su/threads/4047-An-improvisation-on-the-Symbol-Ranking-theme?p=79672&viewfull=1#post79672)

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [January 20, 2024, 4:37pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/3 "2024-01-20T16:37:40Z")

</div>

I guess in a sense you are right that goto cleanup is probably more subjective, I personally don’t like it I find it very messy but I guess it’s not the worst, I just find that having an idiom that tells you “ok if you get an error don’t worry we will execute your cleanup code” is better than to keep track of 10 different label.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 20, 2024, 5:50pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/4 "2024-01-20T17:50:23Z")

</div>

> [@pierrelgol](#):
>
> …than to keep track of 10 different label.

ten?!? 🙂 you’re kidding..  
One label is more than enough:

```c
bool do_smth(... result *r) {

    int fd1 = -1;
    int fd2 = -1;
    void *m1 = NULL;
    void *m2 = NULL;

    fd1 = open(...);
    if (-1 == fd1) {
        ...
        goto __failure;
    }

    fd2 = open(...);
    if (-1 == fd2) {
        ...
        goto __failure;
    }

    m1 = malloc(...);
    if (NULL == m1) {
        ...
        goto __failure;
    }

    m2 = malloc(...);
    if (NULL == m2) {
        ...
        goto __failure;
    }

    r->fd1 = fd1;
    r->fd2 = fd2;
    r->m1 = m1;
    r->m2 = m2;
    return true;

  __failure:
    if (-1 != fd1)
        close(fd1);
    if (-1 != fd2)
        close(fd2);
    if (NULL != m1)
        free(m1);
    if (NULL != m2)
        free(m2);
    return false;
}

```

I’ve never seen more clear cleanup pattern than this one.

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [January 20, 2024, 11:48pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/5 "2024-01-20T23:48:13Z")

</div>

This is more what I had in mind, it always look nice in snippets not really in the real world:

```C
int ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max,
			gfp_t gfp)
{
	XA_STATE(xas, &ida->xa, min / IDA_BITMAP_BITS);
	unsigned bit = min % IDA_BITMAP_BITS;
	unsigned long flags;
	struct ida_bitmap *bitmap, *alloc = NULL;

	if ((int)min < 0)
		return -ENOSPC;

	if ((int)max < 0)
		max = INT_MAX;

retry:
	xas_lock_irqsave(&xas, flags);
next:
	bitmap = xas_find_marked(&xas, max / IDA_BITMAP_BITS, XA_FREE_MARK);
	if (xas.xa_index > min / IDA_BITMAP_BITS)
		bit = 0;
	if (xas.xa_index * IDA_BITMAP_BITS + bit > max)
		goto nospc;

	if (xa_is_value(bitmap)) {
		unsigned long tmp = xa_to_value(bitmap);

		if (bit < BITS_PER_XA_VALUE) {
			bit = find_next_zero_bit(&tmp, BITS_PER_XA_VALUE, bit);
			if (xas.xa_index * IDA_BITMAP_BITS + bit > max)
				goto nospc;
			if (bit < BITS_PER_XA_VALUE) {
				tmp |= 1UL << bit;
				xas_store(&xas, xa_mk_value(tmp));
				goto out;
			}
		}
		bitmap = alloc;
		if (!bitmap)
			bitmap = kzalloc(sizeof(*bitmap), GFP_NOWAIT);
		if (!bitmap)
			goto alloc;
		bitmap->bitmap[0] = tmp;
		xas_store(&xas, bitmap);
		if (xas_error(&xas)) {
			bitmap->bitmap[0] = 0;
			goto out;
		}
	}

	if (bitmap) {
		bit = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, bit);
		if (xas.xa_index * IDA_BITMAP_BITS + bit > max)
			goto nospc;
		if (bit == IDA_BITMAP_BITS)
			goto next;

		__set_bit(bit, bitmap->bitmap);
		if (bitmap_full(bitmap->bitmap, IDA_BITMAP_BITS))
			xas_clear_mark(&xas, XA_FREE_MARK);
	} else {
		if (bit < BITS_PER_XA_VALUE) {
			bitmap = xa_mk_value(1UL << bit);
		} else {
			bitmap = alloc;
			if (!bitmap)
				bitmap = kzalloc(sizeof(*bitmap), GFP_NOWAIT);
			if (!bitmap)
				goto alloc;
			__set_bit(bit, bitmap->bitmap);
		}
		xas_store(&xas, bitmap);
	}
out:
	xas_unlock_irqrestore(&xas, flags);
	if (xas_nomem(&xas, gfp)) {
		xas.xa_index = min / IDA_BITMAP_BITS;
		bit = min % IDA_BITMAP_BITS;
		goto retry;
	}
	if (bitmap != alloc)
		kfree(alloc);
	if (xas_error(&xas))
		return xas_error(&xas);
	return xas.xa_index * IDA_BITMAP_BITS + bit;
alloc:
	xas_unlock_irqrestore(&xas, flags);
	alloc = kzalloc(sizeof(*bitmap), gfp);
	if (!alloc)
		return -ENOMEM;
	xas_set(&xas, min / IDA_BITMAP_BITS);
	bit = min % IDA_BITMAP_BITS;
	goto retry;
nospc:
	xas_unlock_irqrestore(&xas, flags);
	kfree(alloc);
	return -ENOSPC;
}
EXPORT_SYMBOL(ida_alloc_range);

```

(btw that’s from the linux kernel, and sure this is not really the best example of it, but it’s not uncommon to see that in C)

---

<div class="post-metadata">

**Author:** ![slonik-az](https://ziggit.dev/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@slonik-az](https://ziggit.dev/u/slonik-az)\
**Post date:** [January 21, 2024, 1:10am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/6 "2024-01-21T01:10:27Z")

</div>

> [@The linux kernel community is discussing convert the linux kernel from c to modern c++](https://ziggit.dev/t/the-linux-kernel-community-is-discussing-convert-the-linux-kernel-from-c-to-modern-c/2824/13):
>
> “И эти люди запрещают ковыряться мне в носу”  
> I (and google too) do not know how to express this phrase in English.

Very loosely something like this:  
_“And these hypocrites are prohibiting me from picking my nose”_

---

<div class="post-metadata">

**Author:** ![mgord9518](https://ziggit.dev/user_avatar/ziggit.dev/mgord9518/32/2342_2.png) [@mgord9518](https://ziggit.dev/u/mgord9518)\
**Post date:** [January 21, 2024, 1:47am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/7 "2024-01-21T01:47:45Z")

</div>

“whereas in C I do it automatically”

This comes off as more of an experience thing than an actual good language feature. Obviously people who have years of experience in C are going to gravitate towards C ways of doing things.

Most newbie C programmers absolutely abuse goto. I feel like defer/errdefer is easier to grasp and can be mentally carried over from higher level languages like Go and D.

Zig was very natural when I came from Go, C on the other hand is a different world.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 21, 2024, 9:08am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/8 "2024-01-21T09:08:04Z")

</div>

> [@pierrelgol](#):
>
> `goto retry;`

This is really awful.  
And as I said before the only natural use of `goto` is managing cleanup.  
That `goto` is not about cleanup.

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [January 21, 2024, 9:33am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/9 "2024-01-21T09:33:58Z")

</div>

That’s true, and to be fair goto cleanup is not the worst, but I think it is still very error prone, in the sense that, you have to make the goto statement, so you better not forget to close a ressource. Whereas errdefer or defer, they take care of that for you, and if you forget something you can get warnings from the compiler, which you don’t get in C if you forgot a statement in your goto label.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 21, 2024, 9:42am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/10 "2024-01-21T09:42:11Z")

</div>

> [@mgord9518](#):
>
> This comes off as more of an experience thing than an actual good language feature

Yes, that’s true.

> [@mgord9518](#):
>
> I feel like defer/errdefer is easier to grasp

I disagree. Once you’ve seen `goto` based cleanup pattern you grasp it immediately, no explanations is needed at all.  
`defer/errdefer`, on the contrary, require thorough explanations because they are implicit jumps akin `try/catch/finally`.

---

<div class="post-metadata">

**Author:** ![slonik-az](https://ziggit.dev/letter_avatar_proxy/v4/letter/s/ebca7d/32.png) [@slonik-az](https://ziggit.dev/u/slonik-az)\
**Post date:** [January 21, 2024, 9:53am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/11 "2024-01-21T09:53:56Z")

</div>

> [@pierrelgol](#):
>
> That’s true, and to be fair goto cleanup is not the worst, but I think it is still very error prone, in the sense that, you have to make the goto statement, so you better not forget to close a ressource. Whereas errdefer or defer, they take care of that for you, and if you forget something you can get warnings from the compiler, which you don’t get in C if you forgot a statement in your goto label.

Moreover, cleanup operations should be run in reverse order of resource allocations. `defer/errdefer` do it automatically. In C you have to manually maintain correct order.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 21, 2024, 10:01am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/12 "2024-01-21T10:01:09Z")

</div>

> [@slonik-az](#):
>
> Moreover, cleanup operations should be run in reverse order of resource allocations

Just undo everything that failed, in any order.

```c
__in_case_of_failure:
    if (NULL != m) {
        if (NULL != m->a) free(m->a);
        if (-1 != m->fd) {
            int res = 0;
            res = close(m->fd);
            if (-1 == res) {
                printf (
                    "%s: oooops, something went really wrong - close(%d)\n",
                    __func__ , m->fd
                );
            }
       }
       free(m);
    }

```

---

<div class="post-metadata">

**Author:** ![gonzo](https://ziggit.dev/user_avatar/ziggit.dev/gonzo/32/54_2.png) [@gonzo](https://ziggit.dev/u/gonzo)\
**Post date:** [January 21, 2024, 11:26am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/13 "2024-01-21T11:26:50Z")

</div>

For whatever it is worth, I use this pattern in C a lot:

```C
int foo(const char* name) {
  int rc = 0;
  FILE* fp = 0;
  char* buf = 0;
  do {
    fp = fopen("name", "r");
    if (!fp) break;
    buf = malloc(fileSize(fp));
    if (!buf) break;
    // do stuff ...
  } while (0);
  if (fp) fclose(fp);
  if (buf) free(buf);
  return rc;
}

```

It really is a `goto failure` in disguise, but I like the linearity. If there is anything inside the `do ... while(0)` which is a bit more complex, I will usually move it to its own function which also follows this pattern.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 21, 2024, 11:35am UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/14 "2024-01-21T11:35:11Z")

</div>

> [@gonzo](#):
>
> `return rc;`

`rc` is always zero in this example.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 21, 2024, 12:22pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/15 "2024-01-21T12:22:37Z")

</div>

> [@slonik-az](#):
>
> Very loosely something like this:

To be in context of the joke… that sentence is used to express an utmost crux  
when someone is seeing some unusual things being done by others.  
I had wrenched it out of the anecdote, in which a little boy, after spying his  
parents in the bedroom, fairly noted not out loud: “… and these people suppress me picking my nose ?!..”

🙃

---

<div class="post-metadata">

**Author:** ![dude\_the\_builder](https://ziggit.dev/user_avatar/ziggit.dev/dude_the_builder/32/557_2.png) [@dude\_the\_builder](https://ziggit.dev/u/dude_the_builder)\
**Post date:** [January 21, 2024, 1:10pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/16 "2024-01-21T13:10:22Z")

</div>

In an imaginary Ziggified version of C, 47 lines become 21 and in my opinion easier to read:

```c
!void do_smth(... result *r) {
    r->fd1 = try open(...);
    errdefer {
	    ...
	    close(r->fd1);
    }

    r->fd2 = try open(...);
    errdefer {
	    ...
	    close(r->fd2);
    }

    r->m1 = try malloc(...);
    errdefer {
	    ...
	    free(r->m1);
    }

    r->m2 = try malloc(...);
}

```

Not that the C code isn’t clear, it sure is, but Zig is still clear while being less error prone (by not having to jump back and forth from top to bottom to check if everything is handled) and more concise IMO. I know lines of code isn’t a crucial measure of code quality, but I do recall reading somewhere a statistic about how the number of bugs in a project rises along with the number of lines of code.

---

<div class="post-metadata">

**Author:** ![LucasSantos91](https://ziggit.dev/user_avatar/ziggit.dev/lucassantos91/32/440_2.png) [@LucasSantos91](https://ziggit.dev/u/LucasSantos91)\
**Post date:** [January 21, 2024, 2:13pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/17 "2024-01-21T14:13:47Z")

</div>

That’s one of the patterns that was [recommended](https://github.com/ziglang/zig/issues/630#issuecomment-1016957260) when goto was removed from Zig.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 21, 2024, 2:22pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/18 "2024-01-21T14:22:46Z")

</div>

> It’s not really. Zig essentially has goto via labeled breaks

they (labeled breaks) looks very weird.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 21, 2024, 2:42pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/19 "2024-01-21T14:42:43Z")

</div>

> [@dude\_the\_builder](#):
>
> In an imaginary Ziggified version of C, 47 lines become 21 and in my opinion easier to read

A quotation from python (sic!) manifest:

> Explicit is better than implicit

I like `continue`, `break` and `goto` when they are explicit.  
In Zig we have explicit `continue` and (sometimes ugly/strange/weird) `break`  
but we do not have `goto`. Why so? Even D language has it.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [January 21, 2024, 2:58pm UTC](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952/20 "2024-01-21T14:58:17Z")

</div>

> [@dude\_the\_builder](#):
>
> by not having to jump back and forth from top to bottom to check if everything is handled

In my C example all assignments like `r->smth = smth;`  
are located in one solid piece of code,  
whereas in that ziggified version of C they are scattered all around.

[Next page](https://ziggit.dev/t/c-goto-vs-zig-defer-errdefer-break/2952.md?page=2)
