diff --git a/Makefile.in b/Makefile.in index c88e97118..127623632 100644 --- a/Makefile.in +++ b/Makefile.in @@ -25,6 +25,7 @@ KEXT_SOURCES += src/homos-graphs.c KEXT_SOURCES += src/perms.c KEXT_SOURCES += src/planar.c KEXT_SOURCES += src/schreier-sims.c +KEXT_SOURCES += src/safemalloc.c ifdef WITH_INCLUDED_BLISS KEXT_SOURCES += extern/bliss-0.73/defs.cc diff --git a/src/bitarray.c b/src/bitarray.c index e55d3b7da..9bea8259b 100644 --- a/src/bitarray.c +++ b/src/bitarray.c @@ -10,24 +10,22 @@ #include "bitarray.h" -// C headers -#include // for free, calloc, malloc - // GAP headers #include "gap-includes.h" // for Obj, ELM_LIST, ISB_LIST, Fail // Digraphs headers #include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "safemalloc.h" BitArray* new_bit_array(uint16_t const nr_bits) { - BitArray* bit_array = malloc(sizeof(BitArray)); + BitArray* bit_array = safe_malloc(sizeof(BitArray)); bit_array->nr_bits = nr_bits; bit_array->nr_blocks = ((nr_bits % NUMBER_BITS_PER_BLOCK) == 0 ? nr_bits / NUMBER_BITS_PER_BLOCK : nr_bits / NUMBER_BITS_PER_BLOCK + 1); // The previous line is not tested since all the bit arrays we use are // currently of length MAXVERTS = 512. - bit_array->blocks = calloc(bit_array->nr_blocks, NUMBER_BITS_PER_BLOCK); + bit_array->blocks = safe_calloc(bit_array->nr_blocks, NUMBER_BITS_PER_BLOCK); return bit_array; } diff --git a/src/bitarray.h b/src/bitarray.h index 953c63ee8..c7de8157b 100644 --- a/src/bitarray.h +++ b/src/bitarray.h @@ -16,6 +16,7 @@ #include // for bool #include // for size_t #include // for uint16_t +#include // for memset // GAP headers #include "gap-includes.h" // for COUNT_TRUES_BLOCKS, Obj, . . . diff --git a/src/cliques.c b/src/cliques.c index 48ea9ebb8..dfd8f319b 100644 --- a/src/cliques.c +++ b/src/cliques.c @@ -10,9 +10,7 @@ // C headers #include // for true, false, bool -#include // for NULL #include // for uint16_t, uint64_t -#include // for malloc, NULL // GAP headers #include "gap-includes.h" diff --git a/src/conditions.c b/src/conditions.c index e06ec51b5..e9ecd9b1c 100644 --- a/src/conditions.c +++ b/src/conditions.c @@ -17,16 +17,17 @@ // Digraphs headers #include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "safemalloc.h" Conditions* new_conditions(uint16_t const nr1, uint16_t const nr2) { DIGRAPHS_ASSERT(nr1 != 0); DIGRAPHS_ASSERT(nr2 != 0); - Conditions* conditions = malloc(sizeof(Conditions)); + Conditions* conditions = safe_malloc(sizeof(Conditions)); - conditions->bit_array = malloc(sizeof(BitArray*) * nr1 * nr1); - conditions->changed = malloc(nr1 * (nr1 + 1) * sizeof(uint16_t)); - conditions->height = malloc(nr1 * sizeof(uint16_t)); - conditions->sizes = malloc(nr1 * nr1 * sizeof(uint16_t)); + conditions->bit_array = safe_malloc(sizeof(BitArray*) * nr1 * nr1); + conditions->changed = safe_malloc(nr1 * (nr1 + 1) * sizeof(uint16_t)); + conditions->height = safe_malloc(nr1 * sizeof(uint16_t)); + conditions->sizes = safe_malloc(nr1 * nr1 * sizeof(uint16_t)); conditions->nr1 = nr1; conditions->nr2 = nr2; diff --git a/src/digraphs.c b/src/digraphs.c index 4eea7de62..2f20c3999 100644 --- a/src/digraphs.c +++ b/src/digraphs.c @@ -13,17 +13,19 @@ *******************************************************************************/ #include "digraphs.h" -#include "digraphs-config.h" #include // for false, true, bool #include // for uint64_t #include // for NULL, free +#include // for memcpy -#include "bliss-includes.h" // for bliss stuff -#include "cliques.h" -#include "digraphs-debug.h" // for DIGRAPHS_ASSERT -#include "homos.h" // for FuncHomomorphismDigraphsFinder -#include "planar.h" // for FUNC_IS_PLANAR, . . . +#include "bliss-includes.h" // for bliss stuff +#include "cliques.h" // for FuncDigraphsCliquesFinder +#include "digraphs-config.h" // for DIGRAPHS_WITH_INCLUDED_BLISS +#include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "homos.h" // for FuncHomomorphismDigraphsFinder +#include "planar.h" // for FUNC_IS_PLANAR, . . . +#include "safemalloc.h" // for safe_malloc #undef PACKAGE #undef PACKAGE_BUGREPORT @@ -184,7 +186,7 @@ static Obj FuncGABOW_SCC(Obj self, Obj digraph) { comps = NEW_PLIST_IMM(T_PLIST_TAB, n); - stack2 = malloc((4 * n + 2) * sizeof(UInt)); + stack2 = safe_malloc((4 * n + 2) * sizeof(UInt)); frames = stack2 + n + 1; end2 = 0; @@ -292,7 +294,7 @@ static Obj FuncDIGRAPH_CONNECTED_COMPONENTS(Obj self, Obj digraph) { gid = NEW_PLIST_IMM(T_PLIST_EMPTY, 0); gcomps = NEW_PLIST_IMM(T_PLIST_EMPTY, 0); } else { - id = malloc(n * sizeof(UInt)); + id = safe_malloc(n * sizeof(UInt)); for (i = 0; i < n; i++) { id[i] = i; } @@ -308,7 +310,7 @@ static Obj FuncDIGRAPH_CONNECTED_COMPONENTS(Obj self, Obj digraph) { } // "Normalise" id, giving it sensible labels - nid = malloc(n * sizeof(UInt)); + nid = safe_malloc(n * sizeof(UInt)); nrcomps = 0; for (i = 0; i < n; i++) { f = UF_FIND(id, i); @@ -346,8 +348,8 @@ static Obj FuncIS_ACYCLIC_DIGRAPH(Obj self, Obj adj) { nr = LEN_PLIST(adj); // init the buf - ptr = calloc(nr + 1, sizeof(UInt)); - stack = malloc((2 * nr + 2) * sizeof(UInt)); + ptr = safe_calloc(nr + 1, sizeof(UInt)); + stack = safe_malloc((2 * nr + 2) * sizeof(UInt)); for (i = 1; i <= nr; i++) { nbs = ELM_PLIST(adj, i); @@ -416,9 +418,9 @@ static Obj FuncDIGRAPH_LONGEST_DIST_VERTEX(Obj self, Obj adj, Obj start) { return INTOBJ_INT(0); } - ptr = calloc(nr + 1, sizeof(UInt)); - depth = calloc(nr + 1, sizeof(UInt)); - stack = malloc((2 * nr + 2) * sizeof(UInt)); + ptr = safe_calloc(nr + 1, sizeof(UInt)); + depth = safe_calloc(nr + 1, sizeof(UInt)); + stack = safe_malloc((2 * nr + 2) * sizeof(UInt)); level = 1; stack[0] = i; @@ -503,9 +505,9 @@ static Obj FuncDIGRAPH_TRANS_REDUCTION(Obj self, Obj D) { Obj const in_list = FuncDIGRAPH_IN_OUT_NBS(self, FuncOutNeighbours(self, D)); // Create data structures needed for computation - UInt* ptr = calloc(n + 1, sizeof(UInt)); - bool* mat = calloc(n * n, sizeof(bool)); - UInt* stack = malloc((2 * n + 2) * sizeof(UInt)); + UInt* ptr = safe_calloc(n + 1, sizeof(UInt)); + bool* mat = safe_calloc(n * n, sizeof(bool)); + UInt* stack = safe_malloc((2 * n + 2) * sizeof(UInt)); // Start a depth-first search from each source of the digraph for (UInt i = 1; i <= n; i++) { @@ -604,8 +606,8 @@ static Obj FuncDIGRAPH_PATH(Obj self, Obj adj, Obj u, Obj v) { nr = LEN_PLIST(adj); // init the buf - ptr = calloc(nr + 1, sizeof(UInt)); - stack = malloc((2 * nr + 2) * sizeof(UInt)); + ptr = safe_calloc(nr + 1, sizeof(UInt)); + stack = safe_malloc((2 * nr + 2) * sizeof(UInt)); level = 1; stack[0] = i; @@ -673,8 +675,8 @@ Obj FuncIS_ANTISYMMETRIC_DIGRAPH(Obj self, Obj adj) { } // init the buf (is this correct length?) - ptr = calloc(nr + 1, sizeof(UInt)); - stack = malloc((4 * nr + 4) * sizeof(UInt)); + ptr = safe_calloc(nr + 1, sizeof(UInt)); + stack = safe_malloc((4 * nr + 4) * sizeof(UInt)); for (i = 1; i <= nr; i++) { nbs = ELM_PLIST(adj, i); @@ -751,11 +753,11 @@ static Obj FuncIS_STRONGLY_CONNECTED_DIGRAPH(Obj self, Obj digraph) { } nextid = 1; - bag = malloc(n * 4 * sizeof(UInt)); + bag = safe_malloc(n * 4 * sizeof(UInt)); ptr1 = bag; ptr2 = bag + n; fptr = bag + n * 2; - id = calloc(n + 1, sizeof(UInt)); + id = safe_calloc(n + 1, sizeof(UInt)); // first vertex v=1 PLAIN_LIST(ELM_PLIST(digraph, 1)); @@ -817,8 +819,8 @@ static Obj FuncDIGRAPH_TOPO_SORT(Obj self, Obj adj) { } // init the buf - ptr = calloc(nr + 1, sizeof(UInt)); - stack = malloc((2 * nr + 2) * sizeof(UInt)); + ptr = safe_calloc(nr + 1, sizeof(UInt)); + stack = safe_malloc((2 * nr + 2) * sizeof(UInt)); count = 0; for (i = 1; i <= nr; i++) { @@ -912,8 +914,8 @@ static Obj FuncDIGRAPH_SYMMETRIC_SPANNING_FOREST(Obj self, Obj adj) { } // init the buffer - ptr = calloc(nr + 1, sizeof(UInt)); - stack = malloc((2 * nr + 2) * sizeof(UInt)); + ptr = safe_calloc(nr + 1, sizeof(UInt)); + stack = safe_malloc((2 * nr + 2) * sizeof(UInt)); for (i = 1; i <= nr; i++) { // perform DFS only on still-undiscovered non-trivial connected components @@ -1082,7 +1084,7 @@ static Obj FuncIS_MULTI_DIGRAPH(Obj self, Obj digraph) { adj = FuncOutNeighbours(self, digraph); n = DigraphNrVertices(digraph); - seen = calloc(n + 1, sizeof(UInt)); + seen = safe_calloc(n + 1, sizeof(UInt)); for (i = 1; i <= n; i++) { adji = ELM_PLIST(adj, i); @@ -1155,7 +1157,7 @@ static Obj FLOYD_WARSHALL(Obj digraph, } // Initialise the n x n matrix with val1 and val2 - dist = malloc(n * n * sizeof(Int)); + dist = safe_malloc(n * n * sizeof(Int)); for (i = 0; i < n * n; i++) { dist[i] = val1; } @@ -1178,7 +1180,7 @@ static Obj FLOYD_WARSHALL(Obj digraph, if (copy) { // This is the special case for IS_TRANSITIVE_DIGRAPH - adj = malloc(n * n * sizeof(Int)); + adj = safe_malloc(n * n * sizeof(Int)); for (i = 0; i < n * n; i++) { adj[i] = dist[i]; } @@ -1406,7 +1408,7 @@ static Obj FuncDIGRAPH_EQUALS(Obj self, Obj digraph1, Obj digraph2) { out1 = FuncOutNeighbours(self, digraph1); out2 = FuncOutNeighbours(self, digraph2); - buf = calloc(n1, sizeof(Int)); + buf = safe_calloc(n1, sizeof(Int)); // Compare OutNeighbours of each vertex in turn for (i = 1; i <= n1; i++) { @@ -1513,7 +1515,7 @@ static Obj FuncDIGRAPH_LT(Obj self, Obj digraph1, Obj digraph2) { out1 = FuncOutNeighbours(self, digraph1); out2 = FuncOutNeighbours(self, digraph2); - buf = calloc(n1, sizeof(Int)); + buf = safe_calloc(n1, sizeof(Int)); // Compare Sorted(out1[i]) and Sorted(out2[i]) for each vertex i for (i = 1; i <= n1; i++) { diff --git a/src/homos-graphs.c b/src/homos-graphs.c index f7907fff7..7cc728f19 100644 --- a/src/homos-graphs.c +++ b/src/homos-graphs.c @@ -17,18 +17,18 @@ #include "gap-includes.h" // for Obj, Int // Digraphs headers -#include "bliss-includes.h" // for bliss stuff #include "digraphs-config.h" // for DIGRAPHS_WITH_INCLUDED_BLISS #include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "safemalloc.h" // for safe_malloc #include "schreier-sims.h" // for PERM_DEGREE extern Obj GeneratorsOfGroup; Digraph* new_digraph(uint16_t const nr_verts) { DIGRAPHS_ASSERT(nr_verts <= MAXVERTS); - Digraph* digraph = malloc(sizeof(Digraph)); - digraph->in_neighbours = malloc(nr_verts * sizeof(BitArray)); - digraph->out_neighbours = malloc(nr_verts * sizeof(BitArray)); + Digraph* digraph = safe_malloc(sizeof(Digraph)); + digraph->in_neighbours = safe_malloc(nr_verts * sizeof(BitArray)); + digraph->out_neighbours = safe_malloc(nr_verts * sizeof(BitArray)); for (uint16_t i = 0; i < nr_verts; i++) { digraph->in_neighbours[i] = new_bit_array(nr_verts); digraph->out_neighbours[i] = new_bit_array(nr_verts); @@ -39,8 +39,8 @@ Digraph* new_digraph(uint16_t const nr_verts) { Graph* new_graph(uint16_t const nr_verts) { DIGRAPHS_ASSERT(nr_verts <= MAXVERTS); - Graph* graph = malloc(sizeof(Graph)); - graph->neighbours = malloc(nr_verts * sizeof(BitArray)); + Graph* graph = safe_malloc(sizeof(Graph)); + graph->neighbours = safe_malloc(nr_verts * sizeof(BitArray)); for (uint16_t i = 0; i < nr_verts; i++) { graph->neighbours[i] = new_bit_array(nr_verts); } diff --git a/src/homos-graphs.h b/src/homos-graphs.h index 27b82f863..cd73f1a74 100644 --- a/src/homos-graphs.h +++ b/src/homos-graphs.h @@ -16,10 +16,11 @@ #include // for uint16_t // Digraphs headers -#include "bitarray.h" // for BitArray -#include "bliss-includes.h" // for bliss stuff -#include "digraphs-debug.h" // for DIGRAPHS_ASSERT -#include "perms.h" // for PermColl +#include "bitarray.h" // for BitArray +#include "bliss-includes.h" // for bliss stuff +#include "digraphs-config.h" // for DIGRAPHS_WITH_INCLUDED_BLISS +#include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "perms.h" // for PermColl //////////////////////////////////////////////////////////////////////// // Directed graphs (digraphs) diff --git a/src/homos.c b/src/homos.c index c137dbf5e..6418cb3f5 100644 --- a/src/homos.c +++ b/src/homos.c @@ -33,7 +33,9 @@ #include // for NULL #include // for uint16_t, uint64_t #include // for malloc, NULL -#include // for time +#ifdef DIGRAPHS_ENABLE_STATS +#include // for time +#endif // GAP headers #include "gap-includes.h" @@ -46,7 +48,8 @@ #include "digraphs-debug.h" // for DIGRAPHS_ASSERT #include "homos-graphs.h" // for Digraph, Graph, . . . #include "perms.h" // for MAXVERTS, UNDEFINED, PermColl, Perm -#include "schreier-sims.h" // for PermColl, . . . +#include "safemalloc.h" +#include "schreier-sims.h" // for PermColl, . . . //////////////////////////////////////////////////////////////////////////////// // 1. Macros @@ -1596,7 +1599,7 @@ static bool init_data_from_args(Obj digraph1_obj, // srand(time(0)); is_initialized = true; #ifdef DIGRAPHS_ENABLE_STATS - STATS = malloc(sizeof(HomoStats)); + STATS = safe_malloc(sizeof(HomoStats)); #endif DIGRAPH1 = new_digraph(MAXVERTS); @@ -1607,7 +1610,7 @@ static bool init_data_from_args(Obj digraph1_obj, IMAGE_RESTRICT = new_bit_array(MAXVERTS); ORB_LOOKUP = new_bit_array(MAXVERTS); - REPS = malloc(MAXVERTS * sizeof(BitArray*)); + REPS = safe_malloc(MAXVERTS * sizeof(BitArray*)); for (uint16_t i = 0; i < MAXVERTS; i++) { BLISS_GRAPH[i] = bliss_digraphs_new(i); REPS[i] = new_bit_array(MAXVERTS); diff --git a/src/perms.c b/src/perms.c index 09ea279bc..d6ac5f008 100644 --- a/src/perms.c +++ b/src/perms.c @@ -14,15 +14,14 @@ #include "perms.h" -// C headers -#include // for malloc, . . . - // Digraphs package headers #include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "gap-includes.h" // for ErrorQuit, ADDR_PERM2, .. +#include "safemalloc.h" // for safe_malloc Perm new_perm(uint16_t const degree) { DIGRAPHS_ASSERT(degree <= MAXVERTS); - return malloc(degree * sizeof(uint16_t)); + return safe_malloc(degree * sizeof(uint16_t)); } Perm new_perm_from_gap(Obj gap_perm_obj, uint16_t const degree) { @@ -61,8 +60,8 @@ Perm new_perm_from_gap(Obj gap_perm_obj, uint16_t const degree) { } PermColl* new_perm_coll(uint16_t const capacity, uint16_t const degree) { - PermColl* coll = malloc(sizeof(PermColl)); - coll->perms = malloc(capacity * sizeof(Perm)); + PermColl* coll = safe_malloc(sizeof(PermColl)); + coll->perms = safe_malloc(capacity * sizeof(Perm)); for (uint16_t i = 0; i < capacity; ++i) { coll->perms[i] = new_perm(degree); } diff --git a/src/planar.c b/src/planar.c index bbd641c47..373ef2677 100644 --- a/src/planar.c +++ b/src/planar.c @@ -16,8 +16,10 @@ #include // for true and false // Digraphs package headers -#include "digraphs-debug.h" // for DIGRAPHS_ASSERT -#include "digraphs.h" // for DigraphNrVertices, DigraphNrEdges, . . . +#include "digraphs-config.h" // for DIGRAPHS_WITH_INCLUDED_PLANARITY +#include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "digraphs.h" // for DigraphNrVertices, DigraphNrEdges, . . . +#include "gap-includes.h" // for Fail, False, True // edge-addition-planarity-suite headers #if defined(__clang__) diff --git a/src/safemalloc.c b/src/safemalloc.c new file mode 100644 index 000000000..0feabef91 --- /dev/null +++ b/src/safemalloc.c @@ -0,0 +1,34 @@ +/******************************************************************************** +** +*A safemalloc.c Safer memory allocation +** +** +** Copyright (C) 2024 - Daniel Pointon, J. D. Mitchell +** +** This file is free software, see the digraphs/LICENSE. +** +********************************************************************************/ + +#include "safemalloc.h" + +#include // for malloc + +#include "gap-includes.h" + +void* safe_malloc(size_t size) { + void* allocation = malloc(size); + if (allocation == NULL) { + ErrorQuit("Call to malloc(%d) failed, giving up!", (Int) size, 0L); + } + return allocation; +} + +void* safe_calloc(size_t nitems, size_t size) { + void* allocation = calloc(nitems, size); + if (allocation == NULL) { + ErrorQuit( + "Call to calloc(%d, %d) failed, giving up!", (Int) nitems, (Int) size); + } + + return allocation; +} diff --git a/src/safemalloc.h b/src/safemalloc.h new file mode 100644 index 000000000..e367431b8 --- /dev/null +++ b/src/safemalloc.h @@ -0,0 +1,20 @@ +/******************************************************************************** +** +*A safemalloc.h Safer memory allocation +** +** +** Copyright (C) 2024 - Daniel Pointon, J. D. Mitchell +** +** This file is free software, see the digraphs/LICENSE. +** +********************************************************************************/ + +#ifndef DIGRAPHS_SRC_SAFEMALLOC_H_ +#define DIGRAPHS_SRC_SAFEMALLOC_H_ + +#include // for size_t + +void* safe_malloc(size_t size); +void* safe_calloc(size_t nitems, size_t size); + +#endif // DIGRAPHS_SRC_SAFEMALLOC_H_ diff --git a/src/schreier-sims.c b/src/schreier-sims.c index 67c97c020..43af28a2e 100644 --- a/src/schreier-sims.c +++ b/src/schreier-sims.c @@ -15,18 +15,19 @@ #include "schreier-sims.h" // C headers -#include "stdlib.h" // for NULL +#include "stddef.h" // for size_t #include "string.h" // for memset // Digraphs package headers #include "digraphs-debug.h" // for DIGRAPHS_ASSERT +#include "safemalloc.h" // for safe_malloc uint16_t PERM_DEGREE = 0; // Schreier-Sims set up SchreierSims* new_schreier_sims(void) { - SchreierSims* ss = malloc(sizeof(SchreierSims)); + SchreierSims* ss = safe_malloc(sizeof(SchreierSims)); ss->tmp_perm = new_perm(MAXVERTS); for (uint16_t i = 0; i < MAXVERTS; ++i) { ss->strong_gens[i] = new_perm_coll(MAXVERTS, MAXVERTS);