From: Thomas Walker Lynch Date: Fri, 3 May 2019 23:54:49 +0000 (+0200) Subject: da accounting development checkpoint X-Git-Url: https://git.reasoningtechnology.com/style/static/gitweb.js?a=commitdiff_plain;h=5b94ebdeaab8d52866de49d3c5a6d872b606276c;p=subu da accounting development checkpoint --- diff --git a/module/da/makefile b/module/da/makefile index b8832c6..1e1a95a 100644 --- a/module/da/makefile +++ b/module/da/makefile @@ -18,6 +18,8 @@ dep: .PHONY: lib lib: cp $(SRCDIR)/da.lib.h $(INCDIR)/da.h + cp $(SRCDIR)/da_na.lib.h $(INCDIR)/da_na.h + cp $(SRCDIR)/acc.lib.h $(INCDIR)/acc.h $(MAKE) $@ .PHONY: exec diff --git a/module/da/src/acc.lib.c b/module/da/src/acc.lib.c new file mode 100644 index 0000000..f071ac5 --- /dev/null +++ b/module/da/src/acc.lib.c @@ -0,0 +1,76 @@ +/* +dynamic memory accounting + +Alternative version of malloc and free that will invoke accounting for pointers that are allocated +but not freed, or freed but not allocated. + +*/ + +#include "da.lib.h" +#include "da_na.lib.h" +#include "acc.lib.h" + +Da *acc_live_checkers = NULL; + +void acc_init(){ + if( acc_live_checkers == NULL ){ + acc_live_checkers = malloc(sizeof(Da)); + da_na_init(acc_live_checkers, sizeof(AccChecker)); + } + AccChecker *acp = malloc(sizeof(AccChecker)); + da_na_alloc(&(acp->outstanding_malloc), sizeof(void *)); + da_na_alloc(&(acp->spurious_free), sizeof(void *)); + da_na_push(acc_live_checkers, acp); +} +void acc_free(){ + +} +void acc_report(){ +} + +void *acc_malloc(size_t mem_size){ + void *an_allocation_pt = malloc(mem_size); + + // push an_allocation_pt on to all live checkers + AccChecker *acp = acc_live_checkers->base; + while(!da_endq(acc_live_checkers, acp)){ + if(*acp) da_na_push(&(acp->outstanding_malloc), an_allocation_pt); + acp++; + } + + return an_allocation_pt; +} + +void *acc_malloc(size_t mem_size){//pushes pointer onto heap_acc before mallocing + void *temp = malloc(mem_size); + da_na_push(&heap_acc, &temp); + return (void *)temp; +} +void acc_free(void *pt){ + if( accounting == true ) { + void *i = heap_acc.base; + bool present = false; + while( i < (void *)heap_acc.end ){ + if( pt == *(void **)i ){//matches and zeroes out pointer from heap_acc + *(int *)i = 0; + present = true; + if( (i + heap_acc.element_size) == heap_acc.end ){//pops excess 0s from end of heap_acc + void *j = i; + while( (*(int *)j == 0) && ((void *)j >= (void *)heap_acc.base) ){ + da_pop(&heap_acc, NULL); + j-=heap_acc.element_size; + }}} + i++; + } + if( present == false ) da_push(&extra_frees, &pt);//stores pointer in extra_frees if tried to free one that we didn't count + } + free(pt);//frees pointer +} +bool acc_result(){//returns false if accounting wasn't being used or heap_acc is not empty or if we tried to free more pointers than we malloced for + if ( accounting == true ){ + bool flag1 = da_empty(&heap_acc); + bool flag2 = da_empty(&extra_frees); + return flag1 && flag2; + } else return false; +} + diff --git a/module/da/src/acc.lib.h b/module/da/src/acc.lib.h new file mode 100644 index 0000000..353f0ac --- /dev/null +++ b/module/da/src/acc.lib.h @@ -0,0 +1,18 @@ +#ifndef ACC_LIB_H +#define ACC_LIB_H + +typedef struct{ + Da outstanding_malloc; + Da spurious_free; +} AccChecker; + +extern Da *acc_live_checkers; + +#define MALLOC acc_malloc +#define FREE acc_free +#define ACCOUNT acc_start() +#define BALANCE acc_result() +#define CLOSE_ACC da_na_free(&heap_acc); da_na_free(&extra_frees) + + +#endif diff --git a/module/da/src/da.lib.c b/module/da/src/da.lib.c index bea8cfb..226391b 100644 --- a/module/da/src/da.lib.c +++ b/module/da/src/da.lib.c @@ -4,15 +4,17 @@ Dynamic Array Cannot expand an empty array. */ -#include "da.lib.h" - #include #include #include +#include "da.lib.h" +#include "acc.lib.h" + //-------------------------------------------------------------------------------- -// allocation +// constructors / destructors +// this really should be called da_init, as it doesn't do any allocation ... void da_alloc(Da *dap, size_t element_size){ dap->element_size = element_size; dap->size = 4 * element_size; @@ -27,14 +29,6 @@ void da_rewind(Da *dap){ dap->end = dap->base; } -bool da_empty(Da *dap){ - return dap->end == dap->base; -} - -size_t da_length(Da *dap){ - return (dap->end - dap->base)/dap->element_size; -} - void da_rebase(Da *dap, char *old_base, void *pta){ char **pt = (char **)pta; size_t offset = *pt - old_base; @@ -61,8 +55,33 @@ bool da_boundq(Da *dap){ return dap->end > (dap->base + dap->size); } +void da_erase(Da *dap){//same as da_free, don't tell anyone + FREE(dap->base); + dap->size = 0; +} + +//-------------------------------------------------------------------------------- +// status / attributes + +bool da_empty(Da *dap){ + return dap->end == dap->base; +} + +bool da_equal(Da *da_0, Da *da_1){ + return !bcmp(da_0, da_1, sizeof(Da)); +} + +size_t da_length(Da *dap){ + return (dap->end - dap->base)/dap->element_size; +} + +bool da_length_equal(Da *dap0, Da *dap1){ + return da_length(dap0) == da_length(dap1); +} + + //-------------------------------------------------------------------------------- -// putting/taking items +// accessing char *da_index(Da *dap, size_t i){ size_t offset = i * dap->element_size; @@ -71,13 +90,12 @@ char *da_index(Da *dap, size_t i){ } // allocate space for a new element at the end of the array -char *da_push_alloc(Da *dap){ +static char *da_push_alloc(Da *dap){ size_t element_off = dap->end - dap->base; dap->end += dap->element_size; if( dap->end > dap->base + dap->size ) da_expand(dap); return dap->base + element_off; } - char *da_push(Da *dap, void *element){ char *element_pt = da_push_alloc(dap); memcpy(element_pt, element, dap->element_size); @@ -101,6 +119,11 @@ bool da_endq(Da *dap, void *pt){ return (char *)pt >= dap->end; } +// array is a row of elements, pt points at the rightmost element +bool da_right_bound(Da *dap, void *pt){ + return ((char *)pt + dap->element_size) >= dap->end; +} + // passed in f(element_pt, arg_pt) // We have no language support closures, so we pass in an argument for it. // The closure may be set to NULL if it is not needed. @@ -112,21 +135,65 @@ void da_map(Da *dap, void f(void *, void *), void *closure){ } } +//∃, OR map +---> should return the element pointer, same for da_pts_exists + +void *da_exists(Da *dap, bool f(void *, void*), void *closure){ + char *pt = dap->base; + bool result = false; + while( !result && (pt != dap->end) ){ + result = f(pt, closure); + pt += dap->element_size; + } + return result; +} + +//∀, AND map +bool da_all(Da *dap, bool f(void *, void*), void *closure){ + char *pt = dap->base; + bool result = true; + while( result && (pt != dap->end) ){ + result = f(pt, closure); + pt += dap->element_size; + } + return result; +} //-------------------------------------------------------------------------------- -// da being used as a resource manager +// elements are pointers +static da_pts_exists_0(void *element, void *pt){ return element == pt; } +bool da_pts_exists(Da *dap, void *test_element){ + return da_exists(dap, da_pts_exists_0, test_element); +} // elements were MALLOCed, now they will all be FREEd -static void da_free_element(void *pt, void *closure){ +static void da_pts_free_all_0(void *pt, void *closure){ FREE(*(char **)pt); // FREE does not care about the pointer type } - -void da_free_elements(Da *dap){ - da_map(dap, da_free_element, NULL); +void da_pts_free_all(Da *dap){ + da_map(dap, da_pts_free_all_0, NULL); da_rewind(dap); } +// elements are pointers +// ept points at an element, we set *ept to NULL +// we pop all NULLs off the top of the stack +void da_pts_nullify(Da *dap, void **ept){ + if(ept >= dap->base && ept < dap->end){ + *ept = NULL; + } + while( + dap->end > dap->base + && + *(void **)(dap->end - dap->element_size) == NULL + ){ + da_pop(dap, NULL); + } +} + + + //-------------------------------------------------------------------------------- // da is an array of integers @@ -271,27 +338,6 @@ void da_cat(Da *dap0, Da *dap1){ //----------------------------------------------------- -//∃, OR map -bool da_exists(Da *dap, bool f(void *, void*), void *closure){ - char *pt = dap->base; - bool result = false; - while( !result && (pt != dap->end) ){ - result = f(pt, closure); - pt += dap->element_size; - } - return result; -} - -//∀, AND map -bool da_all(Da *dap, bool f(void *, void*), void *closure){ - char *pt = dap->base; - bool result = true; - while( result && (pt != dap->end) ){ - result = f(pt, closure); - pt += dap->element_size; - } - return result; -} //------------------------------------------------------- @@ -307,32 +353,27 @@ da_push(damp, dap0); da_push(damp, dap1); */ -void da_erase(Da *damp){//same as da_free, don't tell anyone - FREE(damp->base); - damp->size = 0; -} - -Da *da_push_row_alloc(Da *damp){ +Da *da_mat_push_row_alloc(Da *damp){ size_t row_off = (Da *)(damp->end) - (Da *)(damp->base); damp->end += damp->element_size; if( damp->end > damp->base + damp->size ) da_expand(damp); return (Da *)(damp->base) + row_off; } -Da *da_push_row(Da *damp, Da *dap){// Dama won't track changes to Das after pushing onto rows - Da *row_pt = da_push_row_alloc(damp); +Da *da_mat_push_row(Da *damp, Da *dap){// Dama won't track changes to Das after pushing onto rows + Da *row_pt = da_mat_push_row_alloc(damp); memcpy(row_pt, dap, damp->element_size); return row_pt; } -void da_push_column(Da *damp, Da *dap, void *fill){ - Da *tran = da_matrix_transpose(damp, fill); - da_push_row(tran, dap); - Da *new_dama = da_matrix_transpose(tran, fill); +void da_mat_push_column(Da *damp, Da *dap, void *fill){ + Da *tran = da_mat_transpose(damp, fill); + da_mat_push_row(tran, dap); + Da *new_dama = da_mat_transpose(tran, fill); //add protection against memory overwrite - expand if necessary memcpy(damp, new_dama, new_dama->size); } -void da_every_row(Da *damp, void f(void *, void *), void *closure){//like every but for rows instead of elements +void da_mat_every_row(Da *damp, void f(void *, void *), void *closure){//like every but for rows instead of elements Da *dpt = (Da *)(damp->base); while( dpt != (Da *)damp->end ){ f(dpt, closure); @@ -340,26 +381,26 @@ void da_every_row(Da *damp, void f(void *, void *), void *closure){//like every } } -// da_every_column uses da_longest and therefore da_longer, written for the purpose of terminating the while loop in the appropriate place +// da_mat_every_column uses da_mat_longest and therefore da_mat_longer, written for the purpose of terminating the while loop in the appropriate place // will return dap1 if equal, cannot determine equality -Da *da_longer(Da *dap0, Da *dap1){ +Da *da_mat_longer(Da *dap0, Da *dap1){ if (da_length(dap0) > da_length(dap1)) return dap0; else return dap1; } // returns Da in DaMa with longest length -Da *da_longest(Da *damp){ +Da *da_mat_longest(Da *damp){ Da *dap = (Da *)(damp->base); Da *longest = (Da *)((damp->base) + sizeof(Da)); while( dap < (Da *)(damp->end) ){ - longest = da_longer(dap,longest); + longest = da_mat_longer(dap,longest); dap++; } return longest; } -void da_every_column(Da *damp, void f(void *, void *), void *closure){//like every but for columns instead of elements +void da_mat_every_column(Da *damp, void f(void *, void *), void *closure){//like every but for columns instead of elements Da *dpt = (Da *)(damp->base); size_t rows = damp->size/damp->element_size; - size_t columns = da_length(da_longest(damp)); + size_t columns = da_length(da_mat_longest(damp)); size_t j = 0; while( j < columns ){ int *col = MALLOC(sizeof(rows*sizeof(int))); @@ -376,13 +417,13 @@ void da_every_column(Da *damp, void f(void *, void *), void *closure){//like eve } } -Da *da_matrix_transpose(Da *damp, void *fill){// all Das must have same element type, will sort to integer, char, or char * transpose function +Da *da_mat_transpose(Da *damp, void *fill){// all Das must have same element type, will sort to integer, char, or char * transpose function Da *dap = (Da *)(damp->base); Da tran; da_alloc(&tran, sizeof(damp->element_size)); Da *transpose = &tran; if( dap->element_size == sizeof(int) ){ int *filler = (int *)fill; - transpose = da_integer_transpose(damp, filler); + transpose = da_mat_ints_transpose(damp, filler); } /*else if( dap->element_size == sizeof(char) ){ char *filler = (char *)fill; @@ -401,10 +442,7 @@ Da *da_matrix_transpose(Da *damp, void *fill){// all Das must have same element // DaMa is a matrix of integers (stored in Das as columns) // integer repeats across columns -bool da_length_equal(Da *dap0, Da *dap1){ - return da_length(dap0) == da_length(dap1); -} -bool da_all_rows_same_length(Da *damp){ +bool da_mat_all_rows_same_length(Da *damp){ Da *dap = (Da *)(damp->base); Da *pt = dap; bool flag = true; @@ -413,10 +451,10 @@ bool da_all_rows_same_length(Da *damp){ } return flag; } -bool da_integer_all_rows_repeat(Da *damp){// if rows are made of repeating integers, then all columns read the same thing +bool da_mat_ints_all_rows_repeat(Da *damp){// if rows are made of repeating integers, then all columns read the same thing Da *dpt = (Da *)(damp->base); bool flag = false; - if( da_all_rows_same_length((Da *)damp) ){// columns can't be equal if rows not all same length, will return false + if( da_mat_all_rows_same_length((Da *)damp) ){// columns can't be equal if rows not all same length, will return false flag = true; while( flag && dpt != (Da *)(damp->end) ){ flag = da_integer_repeats(dpt); // in "da is array of integers" section @@ -426,21 +464,21 @@ bool da_integer_all_rows_repeat(Da *damp){// if rows are made of repeating integ } else return flag; } -bool da_integer_all_columns_repeat(Da *damp){// rows are repeating in transpose = columns are repeating +bool da_mat_ints_all_columns_repeat(Da *damp){// rows are repeating in transpose = columns are repeating int x = 0; //have to pass in fill for transpose, this nullifies effect same_length test - Da *test_da = da_matrix_transpose(damp, &x); - return da_integer_all_rows_repeat(test_da); + Da *test_da = da_mat_transpose(damp, &x); + return da_mat_ints_all_rows_repeat(test_da); } -bool da_integer_repeats_matrix(Da *damp){// all elements in matrix are same - bool flag1 = da_integer_all_rows_repeat(damp); - bool flag2 = da_integer_all_columns_repeat(damp); +bool da_mat_ints_repeats_matrix(Da *damp){// all elements in matrix are same + bool flag1 = da_mat_ints_all_rows_repeat(damp); + bool flag2 = da_mat_ints_all_columns_repeat(damp); return flag1 && flag2; } // to transpose directly from one DaMa to another -Da *da_integer_transpose(Da *damp, int *fill){ +Da *da_mat_ints_transpose(Da *damp, int *fill){ size_t rows = damp->size/damp->element_size; - size_t columns = da_length(da_longest(damp)); + size_t columns = da_length(da_mat_longest(damp)); Da *matrix = damp; Da tran; da_alloc(&tran, sizeof(Da)); @@ -459,16 +497,16 @@ Da *da_integer_transpose(Da *damp, int *fill){ dpt++; i++; } - da_push_row(transpose, &new_row); + da_mat_push_row(transpose, &new_row); j++; } return transpose; } //to create raw matrix image in memory, no longer a Da struct -int *da_integer_to_raw_image_matrix(Da *damp, int fill){ +int *da_mat_ints_to_raw_image_matrix(Da *damp, int fill){ size_t rows = damp->size / damp->element_size; - size_t columns = da_length(da_longest(damp)); + size_t columns = da_length(da_mat_longest(damp)); int *matrix = MALLOC(sizeof(rows*columns));//[rows][columns] int i = 0; Da *dpt = (Da *)(damp->base); @@ -489,10 +527,10 @@ int *da_integer_to_raw_image_matrix(Da *damp, int fill){ } return matrix; } -int *da_integer_to_raw_image_transpose(Da *damp, int fill){ +int *da_mat_ints_to_raw_image_transpose(Da *damp, int fill){ size_t rows = damp->size/damp->element_size; - size_t columns = da_length(da_longest(damp)); - int *matrix = da_integer_to_raw_image_matrix(damp, fill);//[rows][columns] + size_t columns = da_length(da_mat_longest(damp)); + int *matrix = da_mat_ints_to_raw_image_matrix(damp, fill);//[rows][columns] int *transpose = MALLOC(sizeof(columns*rows)); int i, j; for(i=0;ibase == test_el->base; - bool f2 = da_el->end == test_el->end; - bool f3 = da_el->size == test_el->size; - bool f4 = da_el->element_size == test_el->element_size; - return f1 && f2 && f3 && f4; -}//may need to be static? - - -void da_matrix_map(Da **dar, int dar_size, void f(void *, void *), void *closure){ +void da_mat_map(Da **dar, int dar_size, void f(void *, void *), void *closure){ Da **pt = dar; int i = 0; while( i < dar_size ){ diff --git a/module/da/src/da.lib.h b/module/da/src/da.lib.h index 9043cda..43ed5a1 100644 --- a/module/da/src/da.lib.h +++ b/module/da/src/da.lib.h @@ -11,104 +11,86 @@ typedef struct { size_t element_size; } Da; -//#include "da_na.lib.h" - #define RETURN(dap, r) \ - { da_free_elements(dap); return r; } - - -void da_alloc(Da *dap, size_t element_size); -void da_free(Da *dap); -void da_rewind(Da *dap); -bool da_empty(Da *dap); -size_t da_length(Da *dap); -void da_rebase(Da *dap, char *old_base, void *pta); -char *da_expand(Da *dap); -bool da_boundq(Da *dap); - -char *da_index(Da *dap, size_t i); -char *da_push_alloc(Da *dap); -char *da_push(Da *dap, void *element); -bool da_pop(Da *dap, void *element); - -bool da_endq(Da *dap, void *pt); -void da_map(Da *dap, void f(void *, void *), void *closure); - -void da_free_elements(Da *dap); - -void da_ints_print(Da *dap, char *sep); -bool da_integer_repeats(Da *dap); -int da_integer_sum(Da *dap); - - -void da_strings_print(Da *dap, char *sep); - -bool da_strings_exists(Da *string_arrp, char *test_string); -void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *)); -void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *)); - - -char *da_string_input(Da *dap, FILE *file); -void da_string_push(Da *dap0, char *string); - -void da_cat(Da *dap_base, Da *dap_cat); - -void da_present(Da **dar, int dar_size, void *closure); -bool da_equal(Da *da_el, Da *test_el); -void da_matrix_map(Da **dar, int dar_size, void f(void *,void*), void *closure); - -bool da_exists(Da *dap, bool f(void *, void*), void *closure); -bool da_all(Da *dap, bool f(void *, void*), void *closure); - -//matrix functions -void da_erase(Da *damp); -Da *da_push_row_alloc(Da *damp); -Da *da_push_row(Da *damp, Da *dap); -void da_push_column(Da *damp, Da *dap, void *fill); - -void da_every_row(Da *damp, void f(void *, void *), void *closure); -Da *da_longer(Da *dap0, Da *dap1); -Da *da_longest(Da *damp); -void da_every_column(Da *damp, void f(void *, void *), void *closure); - -Da *da_matrix_transpose(Da *damp, void *fill); - -bool da_length_equal(Da *dap0, Da *dap1); -bool da_all_rows_same_length(Da *damp); -bool da_integer_all_rows_repeat(Da *damp); -bool da_integer_all_columns_repeat(Da *damp); -bool da_integer_repeats_matrix(Da *damp); - -Da *da_integer_transpose(Da *damp, int *fill); -int *da_integer_to_raw_image_matrix(Da *damp, int fill); -int *da_integer_to_raw_image_transpose(Da *damp, int fill); - - -/* -Accounting for all the pointers for which we allocated memory on the heap. - -Replacement for malloc and free that allows us to check if all the memory we allocated was freed, and if all the memory we tried to free was actually allocated by keeping registers of pointers in Da structs. - */ - -#define MALLOC da_malloc_counted -#define FREE da_free_counted -#define ACCOUNT da_start_accounting() -#define BALANCE da_result_accounting() -#define CLOSE_ACC da_na_free(&heap_acc); da_na_free(&extra_frees) - -//These variables must be declared at global scope in file that will use them. -extern Da heap_acc; extern Da extra_frees; extern bool accounting; - -void da_start_accounting(); -void *da_malloc_counted(size_t mem_size); -void da_free_counted(void *pt); -bool da_result_accounting(void); - -char *da_na_expand(Da *dap); -char *da_na_push_alloc(Da *dap); -char *da_na_push(Da *dap, void *element); -void da_na_free(Da *dap); - + { da_pts_free_all(dap); return r; } + + +// constructors / destructors +// + void da_alloc(Da *dap, size_t element_size); + void da_free(Da *dap); + void da_rewind(Da *dap); + void da_rebase(Da *dap, char *old_base, void *pta); + char *da_expand(Da *dap); + bool da_boundq(Da *dap); + void da_erase(Da *dap); + +// status / attributes +// + bool da_empty(Da *dap); + bool da_equal(Da *da_0, Da *da_1); + size_t da_length(Da *dap); + bool da_length_equal(Da *dap0, Da *dap1); + +// accessing +// + char *da_index(Da *dap, size_t i); + char *da_push(Da *dap, void *element); + bool da_pop(Da *dap, void *element); + +// iteration, f is given a pointer to an element and a pointer to the closure + bool da_endq(Da *dap, void *pt); + bool da_right_bound(Da *dap, void *pt); + void da_map(Da *dap, void f(void *, void *), void *closure); // this is really 'foreach' to be renamed + bool da_exists(Da *dap, bool f(void *, void*), void *closure); + bool da_all(Da *dap, bool f(void *, void*), void *closure); + +// elements are pointers +// would be better if exists returned NULL or a pointer to the existing element- + bool da_pts_exists(Da *dap, void *test_element); + void da_pts_free_all(Da *dap); // calls free on all elements + void da_pts_nullify(Da *dap, void **ept); // sets *ept to NULL, pops all NULLs from top of stack + +// elements are integers + void da_ints_print(Da *dap, char *sep); + bool da_integer_repeats(Da *dap); + int da_integer_sum(Da *dap); + +// the array itself is a string +// careful if you add a null terminator it will become part of the da_string, affects iteration etc. + char *da_string_input(Da *dap, FILE *file); + void da_string_push(Da *dap0, char *string); + void da_cat(Da *dap_base, Da *dap_cat); + +// when the array holds pointers to C strings + void da_strings_print(Da *dap, char *sep); + bool da_strings_exists(Da *string_arrp, char *test_string); + void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *)); + void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *)); + +// matrix +// There is a top level master da array. Its elements are da arrays, these are said to be rows + void da_mat_map(Da **dar, int dar_size, void f(void *,void*), void *closure); + + Da *da_mat_push_row_alloc(Da *damp); + Da *da_mat_push_row(Da *damp, Da *dap); + void da_mat_push_column(Da *damp, Da *dap, void *fill); + + void da_mat_every_row(Da *damp, void f(void *, void *), void *closure); + Da *da_mat_longer(Da *dap0, Da *dap1); + Da *da_mat_longest(Da *damp); + void da_mat_every_column(Da *damp, void f(void *, void *), void *closure); + + Da *da_mat_transpose(Da *damp, void *fill); + + bool da_mat_all_rows_same_length(Da *damp); + bool da_mat_ints_all_rows_repeat(Da *damp); + bool da_mat_ints_all_columns_repeat(Da *damp); + bool da_mat_ints_repeats_matrix(Da *damp); + + Da *da_mat_ints_transpose(Da *damp, int *fill); + int *da_mat_ints_to_raw_image_matrix(Da *damp, int fill); + int *da_mat_ints_to_raw_image_transpose(Da *damp, int fill); #endif diff --git a/module/da/src/da_na.lib.c b/module/da/src/da_na.lib.c index bc8f183..33f0640 100644 --- a/module/da/src/da_na.lib.c +++ b/module/da/src/da_na.lib.c @@ -1,89 +1,74 @@ /* -Accounting for all the pointers for which we allocated memory on the heap. +Alternative versions of the da array constructors and destructors for avoiding the accounting +versions of malloc and free. -Replacement for malloc and free that allows us to check if all the memory we allocated was freed, and if all the memory we tried to free was actually allocated by keeping registers of pointers in Da structs. */ -#include "da.lib.h" - #include #include #include -//------------------------------------------------------------------ -//FREE and MALLOC replacement +#include "da.lib.h" +#include "da_na.lib.h" -void da_start_accounting(){//assigns properties of heap_acc and extra_frees and sets accounting to true, must be called before other code to be used - heap_acc.element_size = sizeof(void *); - heap_acc.size = 4*sizeof(void *); - heap_acc.base = malloc(heap_acc.size); - heap_acc.end = heap_acc.base; - extra_frees.element_size = sizeof(void *); - extra_frees.size = 4*sizeof(void *); - extra_frees.base = malloc(extra_frees.size); - extra_frees.end = extra_frees.base; - accounting = true; -} -void *da_malloc_counted(size_t mem_size){//pushes pointer onto heap_acc before mallocing - void *temp = malloc(mem_size); - if( accounting == true ) da_na_push(&heap_acc, &temp); - return (void *)temp; -} -void da_free_counted(void *pt){ - if( accounting == true ) { - void *i = heap_acc.base; - bool present = false; - while( i < (void *)heap_acc.end ){ - if( pt == *(void **)i ){//matches and zeroes out pointer from heap_acc - *(int *)i = 0; - present = true; - if( (i + heap_acc.element_size) == heap_acc.end ){//pops excess 0s from end of heap_acc - void *j = i; - while( (*(int *)j == 0) && ((void *)j >= (void *)heap_acc.base) ){ - da_pop(&heap_acc, NULL); - j-=heap_acc.element_size; - }}} - i++; - } - if( present == false ) da_push(&extra_frees, &pt);//stores pointer in extra_frees if tried to free one that we didn't count - } - free(pt);//frees pointer +#undef MALLOC +#undef FREE +#define MALLOC malloc +#define FREE free + +#define da_alloc da_na_alloc +#define da_free da_na_free +#define da_expand da_na_expand +#define da_push_alloc da_na_push_alloc +#define da_push da_na_push +#define da_pts_free_all_0 da_na_pts_free_all_0 +#define da_pts_free_all da_na_pts_free_all + +// the following is just cut and paste from da.lib.c +// ... + +void da_alloc(Da *dap, size_t element_size){ + dap->element_size = element_size; + dap->size = 4 * element_size; + dap->base = MALLOC(dap->size); + dap->end = dap->base; } -bool da_result_accounting(){//returns false if accounting wasn't being used or heap_acc is not empty or if we tried to free more pointers than we malloced for - if ( accounting == true ){ - bool flag1 = da_empty(&heap_acc); - bool flag2 = da_empty(&extra_frees); - return flag1 && flag2; - } else return false; +void da_free(Da *dap){ + FREE(dap->base); + dap->size = 0; } -//------------------------------------------------------------------------- - -//these are redefined with malloc instead of MALLOC because da_malloc_counted will not make it past the push once heap_acc needs to expand -char *da_na_expand(Da *dap){ +char *da_expand(Da *dap){ char *old_base = dap->base; size_t end_offset = dap->end - old_base; size_t new_size = dap->size << 1; - char *new_base = malloc( new_size ); + char *new_base = MALLOC( new_size ); memcpy( new_base, old_base, end_offset + dap->element_size); - free(old_base); + FREE(old_base); dap->base = new_base; dap->end = new_base + end_offset; dap->size = new_size; return old_base; } -char *da_na_push_alloc(Da *dap){ + +// allocate space for a new element at the end of the array +static char *da_push_alloc(Da *dap){ size_t element_off = dap->end - dap->base; dap->end += dap->element_size; - if( dap->end > dap->base + dap->size ) da_na_expand(dap); + if( dap->end > dap->base + dap->size ) da_expand(dap); return dap->base + element_off; } -char *da_na_push(Da *dap, void *element){ - char *element_pt = da_na_push_alloc(dap); +char *da_push(Da *dap, void *element){ + char *element_pt = da_push_alloc(dap); memcpy(element_pt, element, dap->element_size); return element_pt; } -void da_na_free(Da *dap){ - free(dap->base); - dap->size = 0; + +static void da_pts_free_all_0(void *pt, void *closure){ + FREE(*(char **)pt); // FREE does not care about the pointer type +} +void da_pts_free_all(Da *dap){ + da_map(dap, da_pts_free_all_0, NULL); + da_rewind(dap); } + diff --git a/module/da/src/da_na.lib.h b/module/da/src/da_na.lib.h new file mode 100644 index 0000000..aca05cc --- /dev/null +++ b/module/da/src/da_na.lib.h @@ -0,0 +1,27 @@ +#ifndef DA_NA_LIB_H +#define DA_NA_LIB_H +#include +#include +#include + +/* +Alternative versions of the da array constructors and destructors for avoiding the accounting +versions of malloc and free. We use these in the accounting code itself. + +Note the accounting software does not use int, string, strings, or matrix da methods, so those +have not been replaced. + +Why are we afraid to let accounting account for itself? Well otherwise there is a possibility +of a hickup where an array in the accounting code expands while testing a block +of code. + +*/ + +void da_na_alloc(Da *dap, size_t element_size); +void da_na_free(Da *dap); +char *da_na_expand(Da *dap); +char *da_na_push_alloc(Da *dap); +char *da_na_push(Da *dap, void *element); +void da_na_pts_free_all(Da *dap); + +#endif diff --git a/module/da/src/temp.c b/module/da/src/temp.c deleted file mode 100644 index 67014a1..0000000 --- a/module/da/src/temp.c +++ /dev/null @@ -1,20 +0,0 @@ -#include - - -typedef struct { - char *base; - char *end; // one byte/one element off the end of the array - size_t size; // size >= (end - base) + 1; - size_t element_size; -} Da; - - -Da heap_count = { - .element_size = sizeof(void *), - .size = 4*sizeof(void *), - .base = malloc(4*sizeof(void *)), - .end = this.base -}; -void *da_malloc_counted(size_t mem_size); -void da_free_counted(void *pt); - diff --git a/module/da/src/temp.sed b/module/da/src/temp.sed new file mode 100644 index 0000000..6fcf87f --- /dev/null +++ b/module/da/src/temp.sed @@ -0,0 +1,21 @@ +s/da_start_accounting/acc_start/g +s/da_malloc_counted/acc_malloc/g +s/da_free_counted/acc_free/g +s/da_result_accounting/acc_result/g +s/da_free_elements/da_pts_free_all/g +s/da_matrix_map/da_mat_map/g +s/da_push_row_alloc/da_mat_push_row_alloc/g +s/da_push_column/da_mat_push_column/g +s/da_push_row/da_mat_push_row/g +s/da_every_row/da_mat_every_row/g +s/da_longer/da_mat_longer/g +s/da_longest/da_mat_longest/g +s/da_every_column/da_mat_every_column/g +s/da_matrix_transpose/da_mat_transpose/g +s/da_all_rows_same_length/da_mat_all_rows_same_length/g +s/da_integer_all_rows_repeat/da_mat_ints_all_rows_repeat/g +s/da_integer_all_columns_repeat/da_mat_ints_all_columns_repeat/g +s/da_integer_repeats_matrix/da_mat_ints_repeats_matrix/g +s/da_integer_transpose/da_mat_ints_transpose/g +s/da_integer_to_raw_image_matrix/da_mat_ints_to_raw_image_matrix/g +s/da_integer_to_raw_image_transpose/da_mat_ints_to_raw_image_transpose/g \ No newline at end of file