BBS: TELESC.NET.BR Assunto: Win32 debug heap assertion after reading a cached filter filter while De: Rob Swindell Data: Fri, 13 Mar 2026 18:52:45 -0700 ----------------------------------------------------------- https://gitlab.synchro.net/main/sbbs/-/issues/1099#note_8576 Tried to create a small C++ reproduction case for this issue, unsuccessfully. Created xpdev/strlisttest.cpp: ``` #include "str_list.h" #include "threadwrap.h" #include "genwrap.h" #include "dirwrap.h" #include#include #include static char* process_findstr_item(size_t index, char *str, void* cbdata) { SKIP_WHITESPACE(str); truncnl(str); return c_unescape_str(str); } str_list_t findstr_list(const char* fname) { FILE* fp; str_list_t list; if ((fp = fopen(fname, "r")) == NULL) return NULL; list = strListReadFile(fp, NULL, 1000); strListModifyEach(list, process_findstr_item, /* cbdata: */ NULL); printf("Read %s\n", fname); fclose(fp); return list; } class filterFile { public: filterFile() { pthread_mutex_init(&mutex, nullptr); } filterFile(const char* fname) : filterFile() { init(fname); } void init(const char* fname) { strlcpy(this->fname, fname, sizeof this->fname); } filterFile(const filterFile&) = delete; filterFile& operator=(const filterFile&) = delete; ~filterFile() { strListFree(&list); pthread_mutex_destroy(&mutex); } void reset() { fread_count = 0; total_found = 0; timestamp = 0; lastftime_check = 0; strListFree(&list); } std::atomic fread_count{}; std::atomic total_found{}; time_t fchk_interval{1}; // seconds char fname[MAX_PATH + 1]{}; bool listed(const char* str1, const char* str2 = nullptr, struct trash* details = nullptr) { bool result; time_t now = time(nullptr); if (fchk_interval) { pthread_mutex_lock(&mutex); if ((now - lastftime_check) >= fchk_interval) { lastftime_check = now; time_t latest = fdate(fname); if (latest > timestamp) { strListFree(&list); list = findstr_list(fname); timestamp = latest; ++fread_count; } } result = false; //trash_in_list(str1, str2, list, details); pthread_mutex_unlock(&mutex); } if (result) ++total_found; return result; } private: str_list_t list{}; pthread_mutex_t mutex{}; time_t lastftime_check{}; time_t timestamp{}; }; filterFile filter; void thread(void* arg) { filter.listed(""); } int main(int argc, char ** argv) { for (int i = 1; i < argc; ++i) { filter.init(argv[i]); _beginthread(thread, 0, nullptr); SLEEP(2000); printf("Freeing list\n"); filter.reset(); printf("Done freeing list\n"); } return 0; } ``` Build it with this command-line replicating all the options to be sbbs.dll Win32-debug and adding address-sanitizer: ``` cl /GS /analyze- /W3 /Zc:wchar_t /Zi /Gm- /Od /Zc:inline /fp:precise /D "_DEBUG" /D "WIN32" /D "_LIB" /D "LINK_LIST_THREADSAFE" /D "WINVER=0x600" /D "_WIN32_WINNT=0x600" /D "HAS_INTTYPES_H" /D "HAS_STDINT_H" /D "XPDEV_THREAD_SAFE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "_VC80_UPGRADE=0x0600" /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /RTC1 /std:c17 /arch:IA32 /Gd /Oy- /MTd /FC /EHsc /nologo /diagnostics:column /fsanitize=address -DHAS_STDINT_H strlisttest.cpp str_list.c genwrap.c xpprintf.c dirwrap.c threadwrap.c ``` The resulting executable runs just fine: ``` C:\sbbs\src\xpdev>strlisttest s:\sbbs\text\ip.can s:\sbbs\text\host.can s:\sbbs\text\ip.can s:\sbbs\text\host.can s:\sbbs\text\ip-silent.can Read s:\sbbs\text\ip.can Freeing list Done freeing list Read s:\sbbs\text\host.can Freeing list Done freeing list Read s:\sbbs\text\ip.can Freeing list Done freeing list Read s:\sbbs\text\host.can Freeing list Done freeing list Read s:\sbbs\text\ip-silent.can Freeing list Done freeing list ``` I'm out of ideas for now. n --- mSynchronetn hgVertrauen n hHome of Synchronet n gh[vert/cvs/bbs].synchro.net ----------------------------------------------------------- [Voltar]