Skip to content
Snippets Groups Projects
Commit badf030e authored by Vladimir Davydov's avatar Vladimir Davydov
Browse files

core: add x* memory allocation functions

This patch adds xmalloc, xcalloc, xrealloc, xstrdup, and xstrndup helper
functions. Each of them calls the corresponding memory allocation
function and panics if it fails. See the issue description for the full
justification.

Closes #3534

(cherry picked from commit 60dc88ea)
parent 69fc3de6
No related branches found
No related tags found
No related merge requests found
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright 2010-2021, Tarantool AUTHORS, please see AUTHORS file.
*/
#pragma once
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "say.h"
#include "trivia/util.h"
/**
* An x* variant of a memory allocation function calls the original function
* and panics if it fails (i.e. it should never return NULL).
*/
#define xalloc_impl(size, func, args...) \
({ \
void *ret = func(args); \
if (unlikely(ret == NULL)) \
panic("Can't allocate %zu bytes", (size_t)(size)); \
ret; \
})
#define xmalloc(size) xalloc_impl((size), malloc, (size))
#define xcalloc(n, size) xalloc_impl((n) * (size), calloc, (n), (size))
#define xrealloc(ptr, size) xalloc_impl((size), realloc, (ptr), (size))
#define xstrdup(s) xalloc_impl(strlen((s)) + 1, strdup, (s))
#define xstrndup(s, n) xalloc_impl((n) + 1, strndup, (s), (n))
......@@ -56,6 +56,8 @@ add_executable(uuid.test uuid.c core_test_utils.c)
target_link_libraries(uuid.test uuid unit)
add_executable(random.test random.c core_test_utils.c)
target_link_libraries(random.test core unit)
add_executable(xmalloc.test xmalloc.c core_test_utils.c)
target_link_libraries(xmalloc.test core unit)
add_executable(bps_tree.test bps_tree.cc)
target_link_libraries(bps_tree.test small misc)
......
#include "unit.h"
#include "xmalloc.h"
#include <stddef.h>
#include <string.h>
static void
test_xmalloc(void)
{
header();
plan(1);
const int size = 9000;
char *p = xmalloc(size);
isnt(p, NULL, "p != NULL");
if (p != NULL) {
memset(p, 'x', size);
free(p);
}
check_plan();
footer();
}
static void
test_xcalloc(void)
{
header();
plan(2);
const int nmemb = 42;
const int size = 9000;
char *p = xcalloc(nmemb, size);
isnt(p, NULL, "p != NULL");
if (p != NULL) {
bool is_zeroed = true;
for (int i = 0; i < nmemb * size && is_zeroed; i++) {
if (p[i] != 0)
is_zeroed = false;
}
ok(is_zeroed, "p is zeroed")
free(p);
}
check_plan();
footer();
}
static void
test_xrealloc(void)
{
header();
plan(3);
const int size = 9000;
char *p = xrealloc(NULL, size);
isnt(p, NULL, "p != NULL on alloc");
if (p != NULL)
memset(p, 'x', size);
p = xrealloc(p, size * 2);
isnt(p, NULL, "p != NULL on realloc");
if (p != NULL) {
bool is_same = true;
for (int i = 0; i < size && is_same; i++) {
if (p[i] != 'x')
is_same = false;
}
ok(is_same, "p is same after realloc");
memset(p, 'x', size * 2);
free(p);
}
check_plan();
footer();
}
static void
test_xstrdup(void)
{
header();
plan(3);
const int size = 9000;
char *s = xmalloc(size);
isnt(s, NULL, "s != NULL");
if (s != NULL) {
memset(s, 'x', size);
s[size - 1] = 0;
char *copy = xstrdup(s);
isnt(copy, NULL, "copy != NULL");
if (copy != NULL) {
is(strcmp(s, copy), 0, "strcmp(s, copy) == 0");
free(copy);
}
free(s);
}
check_plan();
footer();
}
static void
test_xstrndup(void)
{
header();
plan(6);
const int size = 9000;
const int n = size / 2;
char *s = xmalloc(size);
isnt(s, NULL, "s != NULL");
if (s != NULL) {
memset(s, 'x', size);
s[size - 1] = 0;
char *copy = xstrndup(s, n);
isnt(copy, NULL, "copy != NULL");
if (copy != NULL) {
is(strlen(copy), (size_t)n, "strlen(copy) == n");
is(strncmp(s, copy, n), 0, "strncmp(s, copy, n) == 0");
ok(strncmp(s, copy, n + 1) > 0,
"strncmp(s, copy, n + 1) > 0");
ok(strcmp(s, copy) > 0, "strcmp(s, copy) > 0");
free(copy);
}
free(s);
}
check_plan();
footer();
}
int
main()
{
header();
plan(5);
test_xmalloc();
test_xcalloc();
test_xrealloc();
test_xstrdup();
test_xstrndup();
int rc = check_plan();
footer();
return rc;
}
*** main ***
1..5
*** test_xmalloc ***
1..1
ok 1 - p != NULL
ok 1 - subtests
*** test_xmalloc: done ***
*** test_xcalloc ***
1..2
ok 1 - p != NULL
ok 2 - p is zeroed
ok 2 - subtests
*** test_xcalloc: done ***
*** test_xrealloc ***
1..3
ok 1 - p != NULL on alloc
ok 2 - p != NULL on realloc
ok 3 - p is same after realloc
ok 3 - subtests
*** test_xrealloc: done ***
*** test_xstrdup ***
1..3
ok 1 - s != NULL
ok 2 - copy != NULL
ok 3 - strcmp(s, copy) == 0
ok 4 - subtests
*** test_xstrdup: done ***
*** test_xstrndup ***
1..6
ok 1 - s != NULL
ok 2 - copy != NULL
ok 3 - strlen(copy) == n
ok 4 - strncmp(s, copy, n) == 0
ok 5 - strncmp(s, copy, n + 1) > 0
ok 6 - strcmp(s, copy) > 0
ok 5 - subtests
*** test_xstrndup: done ***
*** main: done ***
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment