Skip to content
Home » All Posts » Is The Goto in C still a Harmful Practice?

Is The Goto in C still a Harmful Practice?

goto in c

Introduction

The goto in c Programming can transfer a program’s control directly to a label within the current function in the code. It allows the program to jump from one part of the code to another. This keyword is generally considered harmful because it could lead to less readable code. However, there are some still some good use cases with the goto keyword that you can utilize.

Typical Function with Error Checking

I like to use goto in a function that allocates and frees memory and returns different error codes for different errors. The goto keyword not only increase the code coverage (a metric to measure your quality of code as higher code coverage the better) but also makes you write less code when error occurs.

Consider this function below that has a memory allocation inside and at the same time checks for several possible errors and will return the error code to function caller immediately when it finds an error.

/* this function returns 0 on success or negative numbers on error */
int gotoExample(const char * name, const char * occupation, int age)
{
	int ret = -1;
	char * some_resource = NULL;
	some_resource = (char * ) malloc(20);
	if (!some_resource)
	{
		printf("failed to allocate memory\n");
		goto error;
	}
	if (!name)
	{
		ret = -2;
		if (some_resource)
			free(some_resource);
		return ret;
	}
	if (age < 0)
	{
		ret = -3;
			if (some_resource)
			free(some_resource);
		return ret;
	}
	if (!occupation)
	{
		ret = -4;
		if (some_resource)
			free(some_resource);
		return ret;
	}
	ret = 0;
	if (some_resource)
		free(some_resource);
	return ret;
}

While the above example is perfectly fine, it has a lot of redundant codes. The function has to call the free() routine to release the memory allocated to some_resource before the function returns. Since there are 4 places of possible returns, there are 4 copies of such code added. What if you forget about one? Then you will get yourself a memory leak problem, which of course we do not want. In addition, if this function returns in the middle of it due to an error, the rest of the function is not run. This is not a desirable practice because it lowers its code coverage rating. Code coverage is one of the popular metrics to measure a program’s effectiveness and higher code coverage the better.

Improve Above Function With Goto Keyword

How to improve the above example? Simple. Use goto in C programming!

Instead of having 4 return keywords and free() routines, we will just have one at the end of the function, but this time, we add a label called error right after ret = 0 line (which indicates a success case). The error label is the destination of the goto keyword that we will put inside each if statement that checks for a particular error. In other words, instead of return in the middle of the function when an error is found, we set the proper error code and jump to the error label, which will release the allocated memory and return the error code. This eliminates redundant codes and make it more organized and readable. Also, because this function returns at the end of it, the code coverage rating for this function would be high.

/* this function returns 0 on success or negative numbers on error */
int gotoExample(const char * name, const char * occupation, int age)
{
	int ret = -1;
	char * some_resource = NULL;
	some_resource = (char * ) malloc(20);
	if (!some_resource)
	{
		printf("failed to allocate memory\n");
		goto error;
	}
	if (!name)
	{
		ret = -2;
		goto error;
	}
	if (age < 0)
	{
		ret = -3;
		goto error;
	}
	if (!occupation)
	{
		ret = -4;
		goto error;
	}

	ret = 0;
error:
	if (some_resource)
		free(some_resource);
	return ret;
}

Summary

Personally, I found the goto keyword the most useful to reduce code redundancy and improve code coverage as illustrated in the examples above. There are other use cases such as retry a particular block of code if it fails to execute by jumping the program in front of it to try again. This could work but it is best to use loops to handle the retry for cases like this.

Related Pages

Join the conversation

Your email address will not be published. Required fields are marked *