Loading content...
Loading content...
In C, there is no built-in exception handling mechanism like try-catch in Java or C++. However, programmers often use the goto statement to handle errors and perform cleanup operations from a single location.
The goto statement transfers program control directly to a labeled statement within the same function.
plaintext
goto label;
/* code */
label:
// statementsplaintext
#include <stdio.h>
int main()
{
printf("Before goto\n");
goto skip;
printf("This line will not execute\n");
skip:
printf("After goto\n");
return 0;
}plaintext
Before goto
After gotoThe goto statement is commonly used in C for:
Resource cleanup
Memory deallocation
File closing
Error handling from multiple locations
Exiting deeply nested blocks
Instead of writing cleanup code multiple times, we can jump to a single cleanup section.
plaintext
#include <stdio.h>
int main()
{
int numerator = 10;
int denominator = 0;
int result;
if (denominator == 0)
{
goto exception;
}
result = numerator / denominator;
printf("Result = %d\n", result);
return 0;
exception:
printf("Exception: Division by zero is not allowed!\n");
return 0;
}plaintext
Exception: Division by zero is not allowed!Condition checks if denominator is zero.
If true, control jumps directly to exception label.
Division operation is skipped.
Error message is displayed.
plaintext
#include <stdio.h>
int main()
{
FILE *file = NULL;
file = fopen("example.txt", "r");
if (file == NULL)
{
printf("Error opening file\n");
goto error;
}
printf("File opened successfully\n");
error:
if (file != NULL)
{
fclose(file);
}
return 0;
}plaintext
Error opening fileIf file opening fails:
Error message is displayed.
Control jumps to the error label.
Cleanup code executes.
Program exits safely.
plaintext
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *arr = NULL;
arr = (int *)malloc(5 * sizeof(int));
if (arr == NULL)
{
printf("Memory allocation failed\n");
goto cleanup;
}
printf("Memory allocated successfully\n");
cleanup:
free(arr);
return 0;
}plaintext
Memory allocated successfullyLarge programs often use multiple labels.
plaintext
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp = NULL;
int *arr = NULL;
fp = fopen("data.txt", "r");
if (fp == NULL)
goto file_error;
arr = (int *)malloc(100 * sizeof(int));
if (arr == NULL)
goto memory_error;
printf("Success\n");
free(arr);
fclose(fp);
return 0;
memory_error:
fclose(fp);
printf("Memory allocation failed\n");
return 0;
file_error:
printf("File opening failed\n");
return 0;
}plaintext
goto cleanup;All cleanup code remains in one place.
Instead of:
plaintext
free(ptr);
fclose(fp);being written many times, it can be written once.
Widely used in:
Linux Kernel
Embedded Systems
Device Drivers
Too many jumps make program flow confusing.
Bad use of goto leads to tangled code.
Example:
plaintext
goto L1;
goto L2;
goto L3;Tracking execution becomes harder.
Whenever possible, use:
Functions
Return codes
Error flags
errno
setjmp() and longjmp()
Example:
plaintext
if(ptr == NULL)
{
return -1;
}instead of:
plaintext
goto error;for simple cases.
Use goto only for cleanup and error handling, not for implementing loops or normal program flow.
Recommended pattern:
plaintext
resource1 = allocate();
if(resource1 == NULL)
goto cleanup;
resource2 = allocate();
if(resource2 == NULL)
goto cleanup;
cleanup:
free(resource1);
free(resource2);C does not provide try-catch exception handling.
goto can be used for error handling and cleanup.
It helps avoid duplicate cleanup code.
Commonly used in low-level and system programming
Overusing goto makes code difficult to maintain.
Use it mainly for resource cleanup and error recovery.