assert()¶
Learning Outcome
Use assert to check invariants and debug.
Introduction
assert() is a macro which tests for conditions which should never occurr in your code.
Applicable subjects
COMP1511, COMP1521, COMP2521, COMP3231
assert¶
The syntax for assert is:
assert(<expression>);
If expression is false, it aborts the program and displays the error to stderr.
To use assert() place the following at the top of your file:
#include <assert.h>
Disabling asserts¶
Asserts can dramatically decrease the performance of a system. There are two main ways of disabling asserts:
Define debug above the include line for assert :
#define NDEBUG #include <assert.h>
Compile wth the -DNDEBUG flag:
$ gcc -DNDEBUG -o <file> <file.c>
Uses¶
Common uses of assert include:
Checking for conditions that should never occurr in a correctly running system.
Discovering programming errors
Assert based testing in COMP1511
Checking that memory has been correctly allocated
To have the system fail in a more controlled manner (rather than abruptly aborting and consuming resources)
Cases where asserts should not be used include:
Handling errors (input or otherwise)
Situations in which recovery is required (asserts abort the program)
Example¶
We can use assert() to check invariants such as whether a pointer is NULL. A common use of assert is to assert that malloc() succeeds (it can fail if the computer runs out of memory). If malloc fails, it will return a NULL pointer, which will cause a segmentation fault when it is dereferenced later in the program. Instead we want to make the program fail in a controlled manner, so we use an ASSERT.
An example of this is given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | //Makes a linked list of length 7 and prints it out
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
int data;
struct node *next;
};
struct node *create_node(int data);
struct node *create_list(int length);
void print_list(struct node *list);
int main(void){
struct node *list1 = create_list(7);
print_list(list1);
return 0;
}
struct node *create_node(int data){
struct node *new = malloc(sizeof(struct node));
assert(new != NULL);
new->data = data;
new->next = NULL;
return new;
}
struct node *create_list(int length) {
struct node *head = NULL;
if (length > 0) {
head = create_node(0);
int i = 1;
struct node *curr = head;
while (i < length) {
curr->next = create_node(i);
curr = curr->next;
i++;
}
}
return head;
}
void print_list(struct node *list){
struct node *curr = list;
while (curr != NULL) {
printf("%d->", curr->data);
curr = curr->next;
}
printf("X\n");
}
|
We can run the program
$ gcc -Wall -Werror -std=c99 -o linked_list linked_list.c
$ ./linked_list
linked_list: linked_list.c:25: create_node: Assertion `new != NULL' failed.
Aborted (core dumped)
In this example, malloc fails and returns a NULL pointer which is picked up by the ASSERT. Alternatively, if there was no assert, the program would crash when the program attempts to set the data field.
Module author: Liz Willer <e.willer@unsw.edu.au>
- Date
2020-02-14