Improved allocation failure reporting
Now it reports file and line number of the function too. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
6f0daf8076
commit
1ea611c90e
|
@ -4,7 +4,7 @@ deps = [
|
|||
dependency('xcb', version: '>=1.9.2'),
|
||||
]
|
||||
|
||||
srcs = [ files('compton.c', 'win.c', 'c2.c', 'x.c', 'config.c', 'vsync.c',
|
||||
srcs = [ files('compton.c', 'win.c', 'c2.c', 'x.c', 'config.c', 'vsync.c', 'utils.c',
|
||||
'diagnostic.c', 'string_utils.c', 'render.c', 'kernel.c', 'log.c')]
|
||||
|
||||
cflags = []
|
||||
|
|
|
@ -11,6 +11,25 @@ char *
|
|||
mstrjoin3(const char *src1, const char *src2, const char *src3);
|
||||
void mstrextend(char **psrc1, const char *src2);
|
||||
|
||||
static inline int uitostr(unsigned int n, char *buf) {
|
||||
int ret = 0;
|
||||
unsigned int tmp = n;
|
||||
while (tmp > 0) {
|
||||
tmp /= 10;
|
||||
ret++;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ret = 1;
|
||||
|
||||
int pos = ret;
|
||||
while (pos--) {
|
||||
buf[pos] = n%10 + '0';
|
||||
n /= 10;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
skip_space_const(const char *src) {
|
||||
if (!src)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "compiler.h"
|
||||
#include "string_utils.h"
|
||||
#include "utils.h"
|
||||
|
||||
/// Report allocation failure without allocating memory
|
||||
void report_allocation_failure(const char *func, const char *file, unsigned int line) {
|
||||
// Since memory allocation failed, we try to print this error message without any
|
||||
// memory allocation. Since logging framework allocates memory (and might even
|
||||
// have not been initialized yet), so we can't use it.
|
||||
char buf[11];
|
||||
int llen = uitostr(line, buf);
|
||||
const char msg1[] = " has failed to allocate memory, ";
|
||||
const char msg2[] = ". Aborting...\n";
|
||||
const struct iovec v[] = {
|
||||
{.iov_base = (void *)func, .iov_len = strlen(func)},
|
||||
{.iov_base = "()", .iov_len = 2},
|
||||
{.iov_base = (void *)msg1, .iov_len = sizeof(msg1) - 1},
|
||||
{.iov_base = "at ", .iov_len = 3},
|
||||
{.iov_base = (void *)file, .iov_len = strlen(file)},
|
||||
{.iov_base = ":", .iov_len = 1},
|
||||
{.iov_base = buf, .iov_len = llen},
|
||||
{.iov_base = (void *)msg2, .iov_len = sizeof(msg2) - 1},
|
||||
};
|
||||
|
||||
writev(STDERR_FILENO, v, ARR_SIZE(v));
|
||||
abort();
|
||||
|
||||
unreachable;
|
||||
}
|
||||
|
||||
// vim: set noet sw=8 ts=8 :
|
13
src/utils.h
13
src/utils.h
|
@ -101,24 +101,21 @@ normalize_d(double d) {
|
|||
return normalize_d_range(d, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void report_allocation_failure(const char *func, const char *file, unsigned int line);
|
||||
|
||||
/**
|
||||
* @brief Quit if the passed-in pointer is empty.
|
||||
*/
|
||||
static inline void *
|
||||
allocchk_(const char *func_name, void *ptr) {
|
||||
allocchk_(const char *func_name, const char *file, unsigned int line, void *ptr) {
|
||||
if (unlikely(!ptr)) {
|
||||
// Since memory allocation failed, we try to print
|
||||
// this error message without any memory allocation.
|
||||
const char msg[] = "(): Failed to allocate memory\n";
|
||||
write(STDERR_FILENO, func_name, strlen(func_name));
|
||||
write(STDERR_FILENO, msg, ARR_SIZE(msg));
|
||||
abort();
|
||||
report_allocation_failure(func_name, file, line);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/// @brief Wrapper of allocchk_().
|
||||
#define allocchk(ptr) allocchk_(__func__, ptr)
|
||||
#define allocchk(ptr) allocchk_(__func__, __FILE__, __LINE__, ptr)
|
||||
|
||||
/// @brief Wrapper of malloc().
|
||||
#define cmalloc(type) ((type *) allocchk(malloc(sizeof(type))))
|
||||
|
|
Loading…
Reference in New Issue