Leaks: non-interactive HSTR w/ EMPTY history has NO leaks

This commit is contained in:
Martin Dvorak 2018-08-17 20:51:33 +02:00
parent 5a56a0a6b6
commit fa7622ae1b
17 changed files with 70 additions and 8 deletions

35
build/test-memleaks.sh Executable file
View file

@ -0,0 +1,35 @@
#!/bin/bash
#
# Copyright (C) 2014-2018 Martin Dvorak <martin.dvorak@mindforger.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Run HSTR w/ 1 history entry to hunt memleaks w/ valgrind
# compile
cd .. && qmake CONFIG+=hstrdebug hstr.pro && make clean && make -j 8
if [ ${?} -ne 0 ]
then
exit 1
fi
# test history file
export HISTFILE=`pwd`/test/resources/.bash_history_valgrind_empty
export HISTFILE=`pwd`/test/resources/.bash_history_valgrind_1_entry
# Valgrind
valgrind --track-origins=yes --tool=memcheck --leak-check=full --show-leak-kinds=all ./hstr -n hist
# Valgrind's GDB
#valgrind --vgdb=yes --vgdb-error=0 --track-origins=yes --tool=memcheck --leak-check=full --show-leak-kinds=all ./hstr -n hist
# eof

View file

@ -14,6 +14,14 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
#########################################################################
#
# QMake build options:
# qmake CONFIG+=hstrdebug ... add extra debug and profiling info
#
#########################################################################
TEMPLATE = app TEMPLATE = app
CONFIG += console CONFIG += console
CONFIG -= app_bundle CONFIG -= app_bundle
@ -46,5 +54,9 @@ HEADERS += \
src/include/hstr.h src/include/hstr.h
# compiler and linker # compiler and linker
QMAKE_CC = ccache gcc hstrdebug {
QMAKE_CC = ccache gcc -g -pg
} else {
QMAKE_CC = ccache gcc
}
QMAKE_LINK = gcc QMAKE_LINK = gcc

View file

@ -1529,20 +1529,28 @@ void hstr_getopt(int argc, char **argv)
} }
} }
void hstr_destroy(void)
{
favorites_destroy(hstr->favorites);
hstr_regexp_destroy(&hstr->regexp);
// blacklist is allocated by hstr struct
blacklist_destroy(&hstr->blacklist, false);
free(hstr);
}
int hstr_main(int argc, char* argv[]) int hstr_main(int argc, char* argv[])
{ {
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
hstr=malloc(sizeof(Hstr)); hstr=malloc(sizeof(Hstr));
hstr_init(); hstr_init();
hstr_get_env_configuration(); hstr_get_env_configuration();
hstr_getopt(argc, argv); hstr_getopt(argc, argv);
blacklist_load(&hstr->blacklist); blacklist_load(&hstr->blacklist);
hstr_interactive(); hstr_interactive();
favorites_destroy(hstr->favorites); hstr_destroy();
free(hstr);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -125,7 +125,7 @@ void blacklist_dump(Blacklist *blacklist)
printf("Command blacklist is empty\n"); printf("Command blacklist is empty\n");
} }
void blacklist_destroy(Blacklist *blacklist) void blacklist_destroy(Blacklist *blacklist, bool freeBlacklist)
{ {
if(blacklist) { if(blacklist) {
if(blacklist->useFile) { if(blacklist->useFile) {
@ -159,6 +159,8 @@ void blacklist_destroy(Blacklist *blacklist)
} }
hashset_destroy(blacklist->set, false); hashset_destroy(blacklist->set, false);
free(blacklist->set); free(blacklist->set);
free(blacklist); if(freeBlacklist) {
free(blacklist);
}
} }
} }

View file

@ -203,6 +203,7 @@ void favorites_destroy(FavoriteItems* favorites)
for(i=0; i<favorites->count; i++) { for(i=0; i<favorites->count; i++) {
free(favorites->items[i]); free(favorites->items[i]);
} }
free(favorites->items);
// TODO hashset destroys keys - no need to destroy items! // TODO hashset destroys keys - no need to destroy items!
hashset_destroy(favorites->set, false); hashset_destroy(favorites->set, false);
free(favorites->set); free(favorites->set);

View file

@ -97,7 +97,7 @@ HistoryItems *get_prioritized_history(int optionBigKeys, HashSet *blacklist)
fprintf(stderr, "\nUnable to read history file from '%s'!\n",historyFile); fprintf(stderr, "\nUnable to read history file from '%s'!\n",historyFile);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
HISTORY_STATE *historyState=history_get_history_state(); HISTORY_STATE* historyState=history_get_history_state();
bool isZsh = isZshParentShell(); bool isZsh = isZshParentShell();
@ -212,10 +212,13 @@ HistoryItems *get_prioritized_history(int optionBigKeys, HashSet *blacklist)
radixsort_destroy(&rs); radixsort_destroy(&rs);
// TODO rankmap (?) and blacklist (?) to be destroyed // TODO rankmap (?) and blacklist (?) to be destroyed
free(historyState);
return prioritizedHistory; return prioritizedHistory;
} else { } else {
free(historyState);
return NULL; return NULL;
} }
} }
void free_prioritized_history(void) void free_prioritized_history(void)

View file

@ -37,6 +37,6 @@ void blacklist_init(Blacklist* blacklist);
void blacklist_load(Blacklist* blacklist); void blacklist_load(Blacklist* blacklist);
bool blacklist_in(Blacklist* blacklist, char *cmd); bool blacklist_in(Blacklist* blacklist, char *cmd);
void blacklist_dump(Blacklist* blacklist); void blacklist_dump(Blacklist* blacklist);
void blacklist_destroy(Blacklist* blacklist); void blacklist_destroy(Blacklist* blacklist, bool freeBlacklist);
#endif #endif

View file

@ -0,0 +1 @@
history-entry-1