#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include <dlfcn.h>
#include "exp_rs.h"
static size_t g_total_allocated = 0;
static size_t g_current_allocated = 0;
static size_t g_peak_allocated = 0;
static size_t g_allocation_count = 0;
static size_t g_free_count = 0;
static int g_tracking_enabled = 0;
static void* (*real_malloc)(size_t) = NULL;
static void (*real_free)(void*) = NULL;
static void* (*real_calloc)(size_t, size_t) = NULL;
static void* (*real_realloc)(void*, size_t) = NULL;
typedef struct {
size_t size;
size_t magic; } alloc_header_t;
#define MAGIC_VALUE 0xDEADBEEF
static void init_memory_hooks() {
static int initialized = 0;
if (!initialized) {
real_malloc = dlsym(RTLD_NEXT, "malloc");
real_free = dlsym(RTLD_NEXT, "free");
real_calloc = dlsym(RTLD_NEXT, "calloc");
real_realloc = dlsym(RTLD_NEXT, "realloc");
initialized = 1;
}
}
void* malloc(size_t size) {
init_memory_hooks();
if (!g_tracking_enabled) {
return real_malloc(size);
}
void* ptr = real_malloc(sizeof(alloc_header_t) + size);
if (!ptr) return NULL;
alloc_header_t* header = (alloc_header_t*)ptr;
header->size = size;
header->magic = MAGIC_VALUE;
g_total_allocated += size;
g_current_allocated += size;
g_allocation_count++;
if (g_current_allocated > g_peak_allocated) {
g_peak_allocated = g_current_allocated;
}
return (char*)ptr + sizeof(alloc_header_t);
}
void free(void* ptr) {
init_memory_hooks();
if (!ptr) return;
if (!g_tracking_enabled) {
real_free(ptr);
return;
}
alloc_header_t* header = (alloc_header_t*)((char*)ptr - sizeof(alloc_header_t));
if (header->magic != MAGIC_VALUE) {
real_free(ptr);
return;
}
g_current_allocated -= header->size;
g_free_count++;
header->magic = 0;
real_free(header);
}
void* calloc(size_t nmemb, size_t size) {
init_memory_hooks();
if (!g_tracking_enabled) {
return real_calloc(nmemb, size);
}
size_t total_size = nmemb * size;
void* ptr = malloc(total_size);
if (ptr) {
memset(ptr, 0, total_size);
}
return ptr;
}
void* realloc(void* ptr, size_t size) {
init_memory_hooks();
if (!g_tracking_enabled) {
return real_realloc(ptr, size);
}
if (!ptr) {
return malloc(size);
}
alloc_header_t* header = (alloc_header_t*)((char*)ptr - sizeof(alloc_header_t));
if (header->magic != MAGIC_VALUE) {
return real_realloc(ptr, size);
}
size_t old_size = header->size;
void* new_ptr = malloc(size);
if (!new_ptr) return NULL;
memcpy(new_ptr, ptr, old_size < size ? old_size : size);
free(ptr);
return new_ptr;
}
void reset_memory_tracking() {
g_total_allocated = 0;
g_current_allocated = 0;
g_peak_allocated = 0;
g_allocation_count = 0;
g_free_count = 0;
}
void print_memory_stats(const char* phase) {
printf("%-50s: %8zu bytes in %4zu allocations\n", phase, g_total_allocated, g_allocation_count);
}
int main() {
printf("=== Context Memory Allocation Analysis ===\n\n");
g_tracking_enabled = 1;
printf("Phase 1: Basic Context Structure\n");
reset_memory_tracking();
void* ctx = exp_rs_context_new();
print_memory_stats("Context with default functions");
printf("\nBreakdown estimate:\n");
printf(" - Base context structure (Rc wrapper)\n");
printf(" - Variable map (heapless IndexMap)\n");
printf(" - Constant map (heapless IndexMap)\n");
printf(" - Array map (heapless IndexMap)\n");
printf(" - Attribute map (heapless IndexMap)\n");
printf(" - Nested array map (heapless IndexMap)\n");
printf(" - Function registry (Rc<FunctionRegistry>)\n");
printf(" - Default math functions (~30-45 functions)\n");
printf("\n");
printf("Phase 2: Adding Parameters\n");
reset_memory_tracking();
exp_rs_context_set_parameter(ctx, "x", 1.0);
print_memory_stats("Adding one parameter");
reset_memory_tracking();
for (int i = 0; i < 10; i++) {
char name[8];
sprintf(name, "p%d", i);
exp_rs_context_set_parameter(ctx, name, (double)i);
}
print_memory_stats("Adding 10 more parameters");
printf("\nPhase 3: Custom Functions\n");
reset_memory_tracking();
print_memory_stats("(Native function registration skipped)");
reset_memory_tracking();
const char* params[] = {"x", "y"};
exp_rs_context_register_expression_function(ctx, "add", params, 2, "x + y");
print_memory_stats("Register one expression function");
printf("\n=== Summary ===\n");
printf("Total allocations: %zu\n", g_allocation_count);
printf("Total deallocations: %zu\n", g_free_count);
printf("Peak memory usage: %zu bytes\n", g_peak_allocated);
printf("Current memory usage: %zu bytes\n", g_current_allocated);
g_tracking_enabled = 0;
exp_rs_context_free(ctx);
return 0;
}