From 6e63cb29d38b598e6746301c926a2e379892d5cb Mon Sep 17 00:00:00 2001 From: Cedric Bastoul Date: Wed, 21 Sep 2011 19:24:57 +0200 Subject: [PATCH] Solve a memory leak for cloned scops --- include/openscop/int.h | 1 + include/openscop/macros.h | 12 ++++++++++++ include/openscop/relation.h | 2 +- source/extensions/textual.c | 4 +--- source/int.c | 31 +++++++++++++++++++++++++++++++ source/interface.c | 7 +++++-- source/relation.c | 28 ++++++++++++++-------------- source/scop.c | 35 +++++++++++++++++------------------ source/vector.c | 8 +++++--- tests/openscop_test.c | 40 ++++++++++++++++++++++++++++++---------- 10 files changed, 117 insertions(+), 51 deletions(-) diff --git a/include/openscop/int.h b/include/openscop/int.h index 63231aa..6ae34b2 100644 --- a/include/openscop/int.h +++ b/include/openscop/int.h @@ -100,6 +100,7 @@ void openscop_int_sread(char *, int, void *, int); void openscop_int_increment(int, void *, int, void *, int); +void openscop_int_decrement(int, void *, int, void *, int); void openscop_int_add(int, void *, int, void *, int, void *, int); void openscop_int_add_ui(int, void *, int, void *, int, int); void openscop_int_mul(int, void *, int, void *, int, void *, int); diff --git a/include/openscop/macros.h b/include/openscop/macros.h index 3393b4d..da181e2 100644 --- a/include/openscop/macros.h +++ b/include/openscop/macros.h @@ -143,5 +143,17 @@ OPENSCOP_error("memory overflow"); \ } while (0) +# define OPENSCOP_strdup(destination, source) \ + do { \ + if (source != NULL) { \ + if (((destination) = strdup(source)) == NULL) \ + OPENSCOP_error("memory overflow"); \ + } \ + else { \ + destination = NULL; \ + OPENSCOP_warning("strdup of a NULL string"); \ + } \ + } while (0) + #endif /* define OPENSCOP_MACROS_H */ diff --git a/include/openscop/relation.h b/include/openscop/relation.h index 7420fe9..cdba242 100644 --- a/include/openscop/relation.h +++ b/include/openscop/relation.h @@ -154,7 +154,7 @@ void openscop_relation_free(openscop_relation_p); /*+*************************************************************************** * Processing functions * *****************************************************************************/ -openscop_relation_p openscop_relation_ncopy(openscop_relation_p, int); +openscop_relation_p openscop_relation_nclone(openscop_relation_p, int); openscop_relation_p openscop_relation_clone(openscop_relation_p); void openscop_relation_replace_vector(openscop_relation_p, openscop_vector_p, int); diff --git a/source/extensions/textual.c b/source/extensions/textual.c index 6b38604..132c623 100644 --- a/source/extensions/textual.c +++ b/source/extensions/textual.c @@ -263,9 +263,7 @@ openscop_textual_p openscop_textual_clone(openscop_textual_p textual) { return NULL; copy = openscop_textual_malloc(); - copy->textual = strdup(textual->textual); - if ((copy->textual == NULL) && (textual->textual != NULL)) - OPENSCOP_error("memory overflow"); + OPENSCOP_strdup(copy->textual, textual->textual); return copy; } diff --git a/source/int.c b/source/int.c index 76fc3d1..003e077 100644 --- a/source/int.c +++ b/source/int.c @@ -436,6 +436,37 @@ void openscop_int_increment(int precision, } +void openscop_int_decrement(int precision, + void * result_base, int result_offset, + void * value_base, int value_offset) { + void * result = openscop_int_address(precision, result_base, result_offset); + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)result = *(long int *)value - (long int)1; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)result = *(long long int *)value - (long long int)1; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: { + mpz_t one; + mpz_init_set_si(one, 1); + mpz_sub(*(mpz_t *)result, *(mpz_t *)value, one); + mpz_clear(one); + break; + } +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + void openscop_int_add(int precision, void * result_base, int result_offset, void * val1_base, int val1_offset, diff --git a/source/interface.c b/source/interface.c index 828739c..13272e1 100644 --- a/source/interface.c +++ b/source/interface.c @@ -219,7 +219,8 @@ openscop_interface_p openscop_interface_malloc() { */ void openscop_interface_free(openscop_interface_p interface) { openscop_interface_p tmp; - + int i = 0; + if (interface == NULL) return; @@ -229,6 +230,7 @@ void openscop_interface_free(openscop_interface_p interface) { free(interface->URI); free(interface); interface = tmp; + i++; } } @@ -253,7 +255,7 @@ openscop_interface_p openscop_interface_nclone(openscop_interface_p interface, while ((interface != NULL) && ((n == -1) || (i < n))) { new = openscop_interface_malloc(); - new->URI = strdup(interface->URI); + OPENSCOP_strdup(new->URI, interface->URI); new->idump = interface->idump; new->dump = interface->dump; new->sprint = interface->sprint; @@ -262,6 +264,7 @@ openscop_interface_p openscop_interface_nclone(openscop_interface_p interface, new->free = interface->free; new->clone = interface->clone; new->equal = interface->equal; + openscop_interface_add(&clone, new); interface = interface->next; i++; diff --git a/source/relation.c b/source/relation.c index 1a00171..7675b3a 100644 --- a/source/relation.c +++ b/source/relation.c @@ -876,22 +876,22 @@ void openscop_relation_free(openscop_relation_p relation) { /** - * openscop_relation_ncopy function: + * openscop_relation_nclone function: * this functions builds and returns a "hard copy" (not a pointer copy) of a - * openscop_relation_t data structure such that the copy is restricted to the + * openscop_relation_t data structure such that the clone is restricted to the * "n" first rows of the relation. This applies to all the parts in the case * of a relation union. - * \param[in] relation The pointer to the relation we want to copy. - * \param[in] n The number of row of the relation we want to copy (the + * \param[in] relation The pointer to the relation we want to clone. + * \param[in] n The number of row of the relation we want to clone (the * special value -1 means "all the rows"). - * \return A pointer to the full copy of the relation union restricted to the + * \return A pointer to the clone of the relation union restricted to the * first n rows of constraint matrix for each part of the union. */ -openscop_relation_p openscop_relation_ncopy(openscop_relation_p relation, - int n) { +openscop_relation_p openscop_relation_nclone(openscop_relation_p relation, + int n) { int i, j; int first = 1, all_rows = 0; - openscop_relation_p copy = NULL, node, previous = NULL; + openscop_relation_p clone = NULL, node, previous = NULL; if (n == -1) all_rows = 1; @@ -901,7 +901,7 @@ openscop_relation_p openscop_relation_ncopy(openscop_relation_p relation, n = relation->nb_rows; if (n > relation->nb_rows) - OPENSCOP_error("not enough rows to copy in the relation"); + OPENSCOP_error("not enough rows to clone in the relation"); node = openscop_relation_pmalloc(relation->precision, n, relation->nb_columns); @@ -919,7 +919,7 @@ openscop_relation_p openscop_relation_ncopy(openscop_relation_p relation, if (first) { first = 0; - copy = node; + clone = node; previous = node; } else { @@ -930,7 +930,7 @@ openscop_relation_p openscop_relation_ncopy(openscop_relation_p relation, relation = relation->next; } - return copy; + return clone; } @@ -938,14 +938,14 @@ openscop_relation_p openscop_relation_ncopy(openscop_relation_p relation, * openscop_relation_clone function: * this function builds and returns a "hard copy" (not a pointer copy) of an * openscop_relation_t data structure (the full union of relation). - * \param[in] relation The pointer to the relation we want to copy. - * \return A pointer to the copy of the union of relations. + * \param[in] relation The pointer to the relation we want to clone. + * \return A pointer to the clone of the union of relations. */ openscop_relation_p openscop_relation_clone(openscop_relation_p relation) { if (relation == NULL) return NULL; - return openscop_relation_ncopy(relation, -1); + return openscop_relation_nclone(relation, -1); } diff --git a/source/scop.c b/source/scop.c index 6a5a827..91ea763 100644 --- a/source/scop.c +++ b/source/scop.c @@ -400,6 +400,7 @@ openscop_scop_p openscop_scop_read(FILE * file) { } scop = openscop_scop_malloc(); + openscop_scop_register_default_extensions(scop); // // II. CONTEXT PART @@ -478,23 +479,6 @@ openscop_scop_p openscop_scop_read(FILE * file) { /** - * openscop_scop_register_default_extensions function: - * this function registers the default OpenScop Library extensions to an - * existing scop. - * \param scop The scop for which default options have to be registered. - */ -static -void openscop_scop_register_default_extensions(openscop_scop_p scop) { - - openscop_interface_add(&scop->registry, openscop_textual_interface()); - openscop_interface_add(&scop->registry, openscop_comment_interface()); - openscop_interface_add(&scop->registry, openscop_arrays_interface()); - openscop_interface_add(&scop->registry, openscop_lines_interface()); - openscop_interface_add(&scop->registry, openscop_irregular_interface()); -} - - -/** * openscop_scop_malloc function: * this function allocates the memory space for a openscop_scop_t structure and * sets its fields with default values. Then it returns a pointer to the @@ -515,7 +499,6 @@ openscop_scop_p openscop_scop_malloc() { scop->extension = NULL; scop->usr = NULL; scop->next = NULL; - openscop_scop_register_default_extensions(scop); return scop; } @@ -551,6 +534,22 @@ void openscop_scop_free(openscop_scop_p scop) { /** + * openscop_scop_register_default_extensions function: + * this function registers the default OpenScop Library extensions to an + * existing scop. + * \param scop The scop for which default options have to be registered. + */ +void openscop_scop_register_default_extensions(openscop_scop_p scop) { + + openscop_interface_add(&(scop->registry), openscop_textual_interface()); + openscop_interface_add(&(scop->registry), openscop_comment_interface()); + openscop_interface_add(&(scop->registry), openscop_arrays_interface()); + openscop_interface_add(&(scop->registry), openscop_lines_interface()); + openscop_interface_add(&(scop->registry), openscop_irregular_interface()); +} + + +/** * openscop_scop_clone function: * This functions builds and returns a "hard copy" (not a pointer copy) * of a openscop_statement_t data structure provided as parameter. diff --git a/source/vector.c b/source/vector.c index 32cffda..ecc2d54 100644 --- a/source/vector.c +++ b/source/vector.c @@ -195,10 +195,12 @@ void openscop_vector_free(openscop_vector_p vector) { int i; if (vector != NULL) { - for (i = 0; i < vector->size; i++) - openscop_int_clear(vector->precision, vector->v, i); + if (vector->v != NULL) { + for (i = 0; i < vector->size; i++) + openscop_int_clear(vector->precision, vector->v, i); - free(vector->v); + free(vector->v); + } free(vector); } } diff --git a/tests/openscop_test.c b/tests/openscop_test.c index 9612922..502f60a 100644 --- a/tests/openscop_test.c +++ b/tests/openscop_test.c @@ -68,7 +68,7 @@ #include #include -#define FORK // Comment that if you want only one process +//#define FORK // Comment that if you want only one process // (best for debugging with valgrind but bad // for make check since any error will // stop the job). @@ -79,11 +79,13 @@ /** * test_file function - * This function tests an onpenscop file. A test has four steps: + * This function tests an onpenscop file. A test has six steps: * 1. read the file to raise the data up to OpenScop data structures, - * 2. dump the data structures to a new OpenScop file, - * 3. read the generated file, - * 4. compare the data structures. + * 2. clone the data structures, + * 3. compare the clone and the original one, + * 4. dump the data structures to a new OpenScop file, + * 5. read the generated file, + * 6. compare the data structures. * If everything went well, the data structure of the two scops are the same. * \param input_name The name of the input file. * \param verbose Verbose option (1 to set, 0 not to set). @@ -92,15 +94,18 @@ int test_file(char * input_name, int verbose) { int success = 0; int failure = 0; - int equal; + int cloning = 0; + int dumping = 0; + int equal = 0; char * output_name; FILE * input_file, * output_file; openscop_scop_p input_scop; openscop_scop_p output_scop; + openscop_scop_p cloned_scop; printf("Testing file %20s... \n", input_name); - // Raise the OpenScop file format to OpenScop data structures. + // PART I. Raise from file. input_file = fopen(input_name, "r"); if (input_file == NULL) { fflush(stdout); @@ -109,8 +114,16 @@ int test_file(char * input_name, int verbose) { } input_scop = openscop_scop_read(input_file); fclose(input_file); - - // Dump the OpenScop data structures to OpenScop file format. + + // PART II. Clone and test. + cloned_scop = openscop_scop_clone(input_scop); + // Compare the two scops. + if (cloning = openscop_scop_equal(input_scop, cloned_scop)) + printf("- cloning succeed\n"); + else + printf("- cloning failed\n"); + + // PART III. Dump to file and test. output_name = tmpnam(NULL); output_file = fopen(output_name, "w"); //openscop_scop_dump(stdout, input_scop); @@ -132,13 +145,20 @@ int test_file(char * input_name, int verbose) { } // Compare the two scops. - if (equal = openscop_scop_equal(input_scop, output_scop)) + if (dumping = openscop_scop_equal(input_scop, output_scop)) + printf("- dumping succeed\n"); + else + printf("- dumping failed\n"); + + // PART IV. Report. + if (equal = (cloning + dumping > 0) ? 1 : 0) printf("Success :-)\n"); else printf("Failure :-(\n"); // Save the planet. openscop_scop_free(input_scop); + openscop_scop_free(cloned_scop); openscop_scop_free(output_scop); remove(output_name); -- 2.11.4.GIT