// Debug version of C API with memory tracking // Compile with: -DMEMORY_DEBUG to enable tracking #include "rag_analyzer_c_api.h" #include "rag_analyzer.h" #include "term.h" #include #include #include #include #ifdef MEMORY_DEBUG #include #include static std::mutex g_memory_mutex; static std::map g_allocations; static size_t g_total_allocated = 0; static size_t g_total_freed = 0; void* debug_malloc(size_t size, const char* file, int line) { void* ptr = malloc(size); std::lock_guard lock(g_memory_mutex); g_allocations[ptr] = size; g_total_allocated += size; fprintf(stderr, "[MEM_DEBUG] ALLOC: %p (%zu bytes) at %s:%d\n", ptr, size, file, line); return ptr; } void debug_free(void* ptr, const char* file, int line) { if (!ptr) return; { std::lock_guard lock(g_memory_mutex); auto it = g_allocations.find(ptr); if (it != g_allocations.end()) { g_total_freed += it->second; g_allocations.erase(it); } } fprintf(stderr, "[MEM_DEBUG] FREE: %p at %s:%d\n", ptr, file, line); free(ptr); } void print_memory_stats() { std::lock_guard lock(g_memory_mutex); fprintf(stderr, "\n[MEM_DEBUG] ===== Memory Statistics =====\n"); fprintf(stderr, "[MEM_DEBUG] Total allocated: %zu bytes\n", g_total_allocated); fprintf(stderr, "[MEM_DEBUG] Total freed: %zu bytes\n", g_total_freed); fprintf(stderr, "[MEM_DEBUG] Current usage: %zu bytes\n", g_total_allocated - g_total_freed); fprintf(stderr, "[MEM_DEBUG] Active allocations: %zu\n", g_allocations.size()); if (!g_allocations.empty()) { fprintf(stderr, "[MEM_DEBUG] Active blocks:\n"); for (const auto& [ptr, size] : g_allocations) { fprintf(stderr, "[MEM_DEBUG] %p: %zu bytes\n", ptr, size); } } fprintf(stderr, "[MEM_DEBUG] ============================\n\n"); } #define DEBUG_MALLOC(size) debug_malloc(size, __FILE__, __LINE__) #define DEBUG_FREE(ptr) debug_free(ptr, __FILE__, __LINE__) #else #define DEBUG_MALLOC(size) malloc(size) #define DEBUG_FREE(ptr) free(ptr) void print_memory_stats() {} #endif extern "C" { RAGAnalyzerHandle RAGAnalyzer_Create(const char* path) { if (!path) return nullptr; try { RAGAnalyzer* analyzer = new RAGAnalyzer(std::string(path)); fprintf(stderr, "[C_API] Created analyzer: %p\n", (void*)analyzer); return static_cast(analyzer); } catch (...) { fprintf(stderr, "[C_API] Failed to create analyzer\n"); return nullptr; } } void RAGAnalyzer_Destroy(RAGAnalyzerHandle handle) { if (handle) { fprintf(stderr, "[C_API] Destroying analyzer: %p\n", handle); RAGAnalyzer* analyzer = static_cast(handle); delete analyzer; } } int RAGAnalyzer_Load(RAGAnalyzerHandle handle) { if (!handle) return -1; RAGAnalyzer* analyzer = static_cast(handle); int ret = analyzer->Load(); fprintf(stderr, "[C_API] Load result: %d\n", ret); return ret; } void RAGAnalyzer_SetFineGrained(RAGAnalyzerHandle handle, bool fine_grained) { if (!handle) return; RAGAnalyzer* analyzer = static_cast(handle); analyzer->SetFineGrained(fine_grained); fprintf(stderr, "[C_API] SetFineGrained: %d\n", fine_grained); } void RAGAnalyzer_SetEnablePosition(RAGAnalyzerHandle handle, bool enable_position) { if (!handle) return; RAGAnalyzer* analyzer = static_cast(handle); analyzer->SetEnablePosition(enable_position); fprintf(stderr, "[C_API] SetEnablePosition: %d\n", enable_position); } int RAGAnalyzer_Analyze(RAGAnalyzerHandle handle, const char* text, RAGTokenCallback callback) { if (!handle || !text || !callback) return -1; fprintf(stderr, "[C_API] Analyze called with text length: %zu\n", strlen(text)); RAGAnalyzer* analyzer = static_cast(handle); Term input; input.text_ = std::string(text); TermList output; int ret = analyzer->Analyze(input, output); fprintf(stderr, "[C_API] Analyze returned: %d, tokens: %zu\n", ret, output.size()); if (ret != 0) { return ret; } // Call callback for each token for (const auto& term : output) { callback(term.text_.c_str(), term.text_.length(), term.word_offset_, term.end_offset_); } return 0; } char* RAGAnalyzer_Tokenize(RAGAnalyzerHandle handle, const char* text) { if (!handle || !text) { fprintf(stderr, "[C_API] Tokenize called with null handle or text\n"); return nullptr; } fprintf(stderr, "[C_API] Tokenize called with text length: %zu\n", strlen(text)); RAGAnalyzer* analyzer = static_cast(handle); std::string result = analyzer->Tokenize(std::string(text)); // Allocate memory for C string char* c_result = static_cast(DEBUG_MALLOC(result.size() + 1)); if (c_result) { std::memcpy(c_result, result.c_str(), result.size() + 1); fprintf(stderr, "[C_API] Tokenize allocated result: %p\n", (void*)c_result); } return c_result; } // Debug function to print memory stats void RAGAnalyzer_PrintMemoryStats() { print_memory_stats(); } } // extern "C"