...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> #include <string.h> extern void log_message(const char *); void f(int i, int width, int prec) { char buffer[20]; char *buf = buffer; int n = sizeof(buffer); const char fmt[] = "i = %*.*i"; n = snprintf(buf, n, fmt, width, prec, i); if (n < 0) { /* Handle snprintf() error */ strcpy(buffer, "unknown error"); goto write_log; } if (n < sizeof(buffer)) { goto write_log; } buf = (char *)malloc(n + 1); if (NULL == buf) { /* Handle malloc() error */ strcpy(buffer, "unknown error"); goto write_log; } n = snprintf(buf, n, fmt, width, prec, i); if (n < 0) { /* Handle snprintf() error */ strcpy(buffer, "unknown error"); } write_log: log_message(buf); if (buf != buffer) { free(buf); } } |
Implementation Details
POSIX
In addition to the C standard library functions mentioned earlier, the following functions defined in POSIX require error checking (list is not all-inclusive).
Function | Successful Return | Error Return |
|
---|---|---|---|
| Pointer to a |
|
|
| Pointer to a |
|
|
|
| Nonzero | Unchanged |
Setting errno
is a POSIX [ISO/IEC 9945:2008] extension to the C Standard. On error, posix_memalign()
returns a value that corresponds to one of the constants defined in the <errno.h>
header. The function does not set errno
. The posix_memalign()
function is optional and is not required to be provided by POSIX-conforming implementations.
Noncompliant Code Example (POSIX)
In the following noncompliant code example, fmemopen()
and open_memstream()
are assumed to succeed. However, if the calls fail, the two file pointers in
and out
will be null and the program will have undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE *out;
FILE *in;
size_t size;
char *ptr;
if (argc != 2) {
/* Handle error */
}
in = fmemopen(argv[1], strlen(argv[1]), "r");
/* Use in */
out = open_memstream(&ptr, &size);
/* Use out */
return 0;
} |
Compliant Solution (POSIX)
A compliant solution avoids assuming that fmemopen()
and open_memstream()
succeed regardless of its arguments and tests the return value of the function before using the file pointers in
and out
:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE *out;
FILE *in;
size_t size;
char *ptr;
if (argc != 2) {
/* Handle error */
}
in = fmemopen(argv[1], strlen(argv[1]), "r");
if (in == NULL){
/* Handle error */
}
/* Use in */
out = open_memstream(&ptr, &size);
if (out == NULL){
/* Handle error */
}
/* Use out */
return 0;
} |
Exceptions
ERR33-EX0: The exception from EXP12-C. Do not ignore values returned by functions still applies. If the return value is inconsequential or if any errors can be safely ignored, such as for functions called because of their side effects, the function should be explicitly cast to void
to signify programmer intent.
...