From 3868334f5c07eeddd75f35ad93a8eb6ac8911f57 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 14 Jun 2010 19:29:38 -0700 Subject: [PATCH] Fix some on error memory leaks in vvp. This patch modifies the vvp main code to cleanup if there was an error compiling the input file. There are still a few issues, but this takes care of most of them. --- vvp/main.cc | 67 ++++++++++++++++++++++++++---------------------- vvp/vpi_tasks.cc | 17 ++++++++++++ 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/vvp/main.cc b/vvp/main.cc index 87d9eb110..38f740a92 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -192,6 +192,41 @@ void set_delay_selection(const char* sel) delete[] sel; } +static void final_cleanup() +{ + /* + * We only need to cleanup the memory if we are checking with valgrind. + */ +#ifdef CHECK_WITH_VALGRIND + /* Clean up the file name table. */ + for (vector::iterator cur = file_names.begin(); + cur != file_names.end() ; cur++) { + delete[] *cur; + } + /* Clear the static result buffer. */ + (void)need_result_buf(0, RBUF_DEL); + codespace_delete(); + root_table_delete(); + def_table_delete(); + vpi_mcd_delete(); + dec_str_delete(); + modpath_delete(); + vpi_handle_delete(); + udp_defns_delete(); + island_delete(); + signal_pool_delete(); + vvp_net_pool_delete(); + ufunc_pool_delete(); +#endif + /* + * Unload the VPI modules. This is essential for MinGW, to ensure + * dump files are flushed before the main process terminates, as + * the DLL termination code is called after all remaining open + * files are automatically closed. + */ + load_module_delete(); +} + unsigned module_cnt = 0; const char*module_tab[64]; @@ -385,6 +420,7 @@ int main(int argc, char*argv[]) if (compile_errors > 0) { vpi_mcd_printf(1, "%s: Program not runnable, %u errors.\n", design_path, compile_errors); + final_cleanup(); return compile_errors; } @@ -463,36 +499,7 @@ int main(int argc, char*argv[]) count_gen_events, count_gen_pool()); } -/* - * We only need to cleanup the memory if we are checking with valgrind. - */ -#ifdef CHECK_WITH_VALGRIND - /* Clean up the memory. */ - for (vector::iterator cur = file_names.begin(); - cur != file_names.end() ; cur++) { - delete[] *cur; - } - (void)need_result_buf(0, RBUF_DEL); - codespace_delete(); - root_table_delete(); - def_table_delete(); - vpi_mcd_delete(); - dec_str_delete(); - modpath_delete(); - vpi_handle_delete(); - udp_defns_delete(); - island_delete(); - signal_pool_delete(); - vvp_net_pool_delete(); - ufunc_pool_delete(); -#endif -/* - * Unload the VPI modules. This is essential for MinGW, to ensure - * dump files are flushed before the main process terminates, as - * the DLL termination code is called after all remaining open - * files are automatically closed. -*/ - load_module_delete(); + final_cleanup(); return vvp_return_value; } diff --git a/vvp/vpi_tasks.cc b/vvp/vpi_tasks.cc index 6b43efae3..428620935 100644 --- a/vvp/vpi_tasks.cc +++ b/vvp/vpi_tasks.cc @@ -713,6 +713,18 @@ void print_vpi_call_errors() free(vpi_call_error_lst); } +static void cleanup_vpi_call_args(unsigned argc, vpiHandle*argv) +{ +#ifdef CHECK_WITH_VALGRIND + if (argc) { + struct __vpiSysTaskCall*obj = new struct __vpiSysTaskCall; + obj->nargs = argc; + obj->args = argv; + vpi_call_delete(&obj->base); + } +#endif +} + /* * A vpi_call is actually built up into a vpiSysTaskCall VPI object * that refers back to the vpiUserSystf VPI object that is the @@ -736,6 +748,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid, struct __vpiUserSystf*defn = vpip_find_systf(name); if (defn == 0) { add_vpi_call_error(VPI_CALL_NO_DEF, name, file_idx, lineno); + cleanup_vpi_call_args(argc, argv); return 0; } @@ -744,6 +757,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid, if (vwid != 0 || fnet != 0) { add_vpi_call_error(VPI_CALL_TASK_AS_FUNC, name, file_idx, lineno); + cleanup_vpi_call_args(argc, argv); return 0; } assert(vbit == 0); @@ -754,6 +768,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid, if (func_as_task_err) { add_vpi_call_error(VPI_CALL_FUNC_AS_TASK, name, file_idx, lineno); + cleanup_vpi_call_args(argc, argv); return 0; } else if (func_as_task_warn) { add_vpi_call_error(VPI_CALL_FUNC_AS_TASK_WARN, @@ -818,6 +833,8 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid, void vpi_call_delete(vpiHandle item) { struct __vpiSysTaskCall*obj = (struct __vpiSysTaskCall *) item; + /* The object can be NULL if there was an error. */ + if (!obj) return; for (unsigned arg = 0; arg < obj->nargs; arg += 1) { switch (obj->args[arg]->vpi_type->type_code) { case vpiConstant: