ഹായ്, MacOS-ലും C പ്രോഗ്രാമിംഗിലും എന്നെ സന്തോഷിപ്പിക്കുന്ന ഒരു പരിഹാരം ഇന്ന് ഞാൻ പങ്കിടാൻ ആഗ്രഹിക്കുന്നു. മെമ്മറി ലീക്കുകൾ പരിശോധിക്കാൻ അനുവദിച്ച മെമ്മറി ട്രാക്കുചെയ്യുന്നു. ഇത് വളരെ ശ്രദ്ധാലുക്കളാണ്, നഷ്ടപ്പെട്ട മെമ്മറി കണ്ടെത്തുന്നു. പ്രവർത്തനക്ഷമമാക്കുക എന്നതിൻ്റെ കമൻ്റ് ഔട്ട് നിർവചനം വഴി ഇത് വളരെ ഗംഭീരമായി പ്രവർത്തനരഹിതമാക്കാം. ഒരുപക്ഷേ Linux-ലെ Valgrind പോലെയല്ല, പക്ഷേ MacOS-ൽ എനിക്ക് വളരെ രസകരമാണ്. ആസ്വദിക്കൂ!
// to enable keep it, to disable make next line commented #define MEM_LEAKS_DETECTION // to usage use CALLOC and FREE defined macros // undefine above if you done with tracking #ifndef MEM_TRACK #define MEM_TRACK typedef struct allocation_node { void *pointer; size_t size; const char *file; int line; time_t timestamp; struct allocation_node *next; } allocation_node; static allocation_node *allocation_head = NULL; void add_allocation(void *ptr, size_t size, const char *file, int line) { auto *node = (allocation_node *)malloc(sizeof(allocation_node)); if (!node) { fprintf(stderr, "failed to track allocation at %s:%d\n", file, line); exit(EXIT_FAILURE); } if (0) { allocation_node **current = &allocation_head; while (*current) { if (strcmp((*current)->file, file) == 0 && (*current)->line == line) { allocation_node *to_free = *current; *current = (*current)->next; free(to_free); break; } current = &(*current)->next; } } node->pointer = ptr; node->size = size; node->file = file; node->line = line; node->timestamp = time(0); node->next = allocation_head; allocation_head = node; } void remove_allocation(void *ptr, const char *file, int line) { allocation_node **current = &allocation_head; while (*current) { if ((void*)(*current)->pointer == (void*)ptr) { allocation_node *to_free = *current; *current = (*current)->next; free(to_free); return; } current = &(*current)->next; } fprintf(stderr, "warning: attempt to free untracked or already freed pointer %p at %s:%d\n", ptr, file, line); exit(EXIT_FAILURE); } void check_for_leaks() { allocation_node *current = allocation_head; time_t now = time(0); int detected = 0; while (current) { double seconds_elapsed = difftime(now, current->timestamp); if (seconds_elapsed >= 10) { detected = 1; fprintf(stderr, " leak detected! pointer: %p, Size: %zu, allocated at %s:%d, time elapsed: %.0f seconds\n", current->pointer, current->size, current->file, current->line, seconds_elapsed); } current = current->next; } if (detected) exit(EXIT_FAILURE); } void print_allocations() { allocation_node *current = allocation_head; fprintf(stderr, "active allocations:\n"); while (current) { fprintf(stderr, " pointer: %p, size: %zu, allocated at %s:%d, timestamp: %ld\n", current->pointer, current->size, current->file, current->line, current->timestamp); current = current->next; } } void* tracked_calloc(size_t count, size_t size, const char *file, int line) { void *ptr = calloc(count, size); if (!ptr) { fprintf(stderr, "memory allocation failed at %s:%d (count: %zu, size: %zu)\n", file, line, count, size); exit(EXIT_FAILURE); } add_allocation(ptr, count * size, file, line); //fprintf(stdut, "allocated memory at %p in %s:%d (count: %zu, size: %zu)\n", &ptr, file, line, count, size); return ptr; } void* tracked_track(void *ptr, const char *file, int line) { if (!ptr) { fprintf(stderr, "memory allocation failed at %s:%d (size: %zu)\n", file, line, sizeof(ptr)); exit(EXIT_FAILURE); } add_allocation(ptr, sizeof(ptr), file, line); //fprintf(stdout, "allocated memory at %p in %s:%d (size: %zu)\n", ptr, file, line, sizeof(ptr)); return ptr; } void tracked_free(void *ptr, const char *file, int line) { if (ptr) { remove_allocation(ptr, file, line); free(ptr); //fprintf(stderr, "freed memory at %p in %s:%d\n", ptr, file, line); } else { fprintf(stderr, "attempt to free NULL pointer in %s:%d\n", file, line); } check_for_leaks(); } #ifdef MEM_LEAKS_DETECTION #define CALLOC(count, size) tracked_calloc((count), (size), __FILE__, __LINE__) #define FREE(ptr) tracked_free(ptr, __FILE__, __LINE__) #else #define CALLOC(count, size) calloc(count, size) #define FREE(ptr) free(ptr) #endif #endif
നന്ദി!