Advertisement
Tarferi

Memory management implementation

Nov 5th, 2020
2,453
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.98 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. // Declare the functions so they can be defined later and are linked to their correct identifiers
  5. #define malloc malloc_%RANDOM%
  6. #define aligned_alloc aligned_alloc_%RANDOM%
  7. #define calloc calloc_%RANDOM%
  8. #define realloc realloc_%RANDOM%
  9. #define free free_%RANDOM%
  10.  
  11. void* malloc(unsigned int sz);
  12. void* aligned_alloc(unsigned int alignment, unsigned int sz);
  13. void* calloc(unsigned int num, unsigned int sz);
  14. void* realloc(void* ptr, unsigned int sz);
  15. void free(void* ptr);
  16.  
  17.  
  18. #define main user_main_%RANDOM%
  19.  
  20.  
  21. // User code
  22. int main(int argc, char** argv) {
  23.     return 0;
  24. }
  25.  
  26.  
  27.  
  28. // End of user code
  29.  
  30.  
  31. #define MALLOC_MEM_BLOCK_SIZE_%RANDOM% 1024
  32. #define MALLOC_MEM_BLOCK_COUNT_%RANDOM% 1024
  33. #define MALLOC_MEM_BLOCK_COUNT_PRE_%RANDOM% 1024
  34. #define MALLOC_MEM_BLOCK_COUNT_POST_%RANDOM% 1024
  35.  
  36. struct t_memory_%RANDOM%{
  37.     struct {
  38.         void(*init_memory)();
  39.         void(*check_memory_after_end)();
  40.         void*(*malloc_init_block)(int, unsigned int);
  41.         void*(*malloc)(unsigned int);
  42.         void(*free)(void*);
  43.         void*(*realloc)(void* ptr, unsigned int sz);
  44.         void*(*calloc)(unsigned int num, unsigned int sz);
  45.         void*(*aligned_alloc)(unsigned int alignment, unsigned int sz);
  46.     } functions;
  47.     int(*userMain)(int, char**);
  48.     struct {
  49.         char used;
  50.         unsigned int sz;
  51.         char memoryPre[MALLOC_MEM_BLOCK_COUNT_PRE_%RANDOM%];
  52.         char memory[MALLOC_MEM_BLOCK_SIZE_%RANDOM%];
  53.         char memoryPost[MALLOC_MEM_BLOCK_COUNT_POST_%RANDOM%];
  54.     } mallocated_memory[MALLOC_MEM_BLOCK_COUNT_%RANDOM%];
  55.     int MALLOC_MEM_BLOCK_COUNT;
  56.     int MALLOC_MEM_BLOCK_SIZE;
  57.     int MALLOC_MEM_BLOCK_COUNT_PRE;
  58.     int MALLOC_MEM_BLOCK_COUNT_POST;
  59.  
  60.     struct {
  61.         int used_blocks;
  62.         int available_blocks;
  63.         int last_init_block;
  64.         int available_allocations;
  65.     } config;
  66.     struct {
  67.         int mem_leaks;
  68.         int invalid_frees;
  69.         int invalid_realloc;
  70.         int zero_allocs;
  71.         int negative_allocs;
  72.         int big_allocs;
  73.         int too_many_allocs;
  74.         int writes_before;
  75.         int writes_beyond;
  76.     } stats;
  77. } memory_%RANDOM%;
  78.  
  79. void check_memory_after_end_%RANDOM%() {
  80.     struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  81.  
  82.     for(int i = 0; i < mem->config.last_init_block; i++) {
  83.         if(mem->mallocated_memory[i].used){
  84.             mem->stats.mem_leaks++;
  85.         }
  86.     }
  87.     if (
  88.         mem->stats.mem_leaks > 0 ||
  89.         mem->stats.invalid_frees > 0 ||
  90.         mem->stats.zero_allocs > 0 ||
  91.         mem->stats.negative_allocs > 0 ||
  92.         mem->stats.big_allocs > 0 ||
  93.         mem->stats.too_many_allocs > 0 ||
  94.         mem->stats.writes_before > 0 ||
  95.         mem->stats.writes_beyond > 0 ||
  96.         mem->stats.invalid_realloc > 0
  97.     ) {
  98.         printf("Memory Error: "
  99.                "leaks: %d, "
  100.                "invalid frees: %d, "
  101.                "zero mallocs: %d, "
  102.                "negative mallocs: %d, "
  103.                "big mallocs: %d, "
  104.                "too many allocs: %d, "
  105.                "writes beyond: %d, "
  106.                "writes before: %d, "
  107.                "invalid realloc: %d, ",
  108.             mem->stats.mem_leaks,
  109.             mem->stats.invalid_frees,
  110.             mem->stats.zero_allocs,
  111.             mem->stats.negative_allocs,
  112.             mem->stats.big_allocs,
  113.             mem->stats.too_many_allocs,
  114.             mem->stats.writes_before,
  115.             mem->stats.writes_beyond,
  116.             mem->stats.invalid_realloc
  117.         );
  118.     }
  119.  
  120. }
  121.  
  122. void* malloc_init_block_%RANDOM%(int blockIndex, unsigned int sz) {
  123.     struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  124.  
  125.     mem->mallocated_memory[blockIndex].used = 1;
  126.     for(int o = 0; o < mem->MALLOC_MEM_BLOCK_COUNT_PRE; o++) {
  127.         mem->mallocated_memory[blockIndex].memoryPre[o] = 0;
  128.     }
  129.     for(int o = 0; o < mem->MALLOC_MEM_BLOCK_COUNT_POST; o++) {
  130.         mem->mallocated_memory[blockIndex].memoryPost[o] = 0;
  131.     }
  132.     for(int o = 0; o < mem->MALLOC_MEM_BLOCK_SIZE; o++) {
  133.         mem->mallocated_memory[blockIndex].memory[o] = 0;
  134.     }
  135.     mem->mallocated_memory[blockIndex].used = 1;
  136.  
  137.  
  138.     mem->config.used_blocks++;
  139.     mem->mallocated_memory[blockIndex].sz = sz;
  140.     return &(mem->mallocated_memory[blockIndex].memory);
  141. }
  142.  
  143. void* malloc(unsigned int sz) {
  144.     struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  145.  
  146.     if(mem->config.available_allocations < 0) {
  147.         mem->config.available_allocations = mem->MALLOC_MEM_BLOCK_COUNT;
  148.     }
  149.  
  150.     if (mem->config.used_blocks >= mem->config.available_allocations) {
  151.         return 0;
  152.     }
  153.  
  154.     if(sz > (unsigned int) mem->MALLOC_MEM_BLOCK_SIZE) {
  155.         mem->stats.big_allocs++;
  156.         return 0;
  157.     } else if( ((int)sz) < 0) {
  158.         mem->stats.negative_allocs++;
  159.         return 0;
  160.     } else if(sz == 0) {
  161.         mem->stats.zero_allocs++;
  162.         return 0;
  163.     }
  164.  
  165.  
  166.     if(mem->config.used_blocks == mem->MALLOC_MEM_BLOCK_COUNT) {
  167.         return 0;
  168.     } else {
  169.         for(int i = 0; i < mem->config.last_init_block; i++) {
  170.             if(mem->mallocated_memory[i].used == 0) {
  171.                 return mem->functions.malloc_init_block(i, sz);
  172.             }
  173.         }
  174.  
  175.         mem->config.last_init_block++;
  176.         return mem->functions.malloc_init_block(mem->config.last_init_block - 1, sz);
  177.     }
  178. }
  179.  
  180. void free(void* ptr) {
  181.     struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  182.  
  183.     for(int i = 0; i < mem->config.last_init_block; i++) {
  184.         if((&(mem->mallocated_memory[i].memory)) == ptr) { // Our memory
  185.             if (mem->mallocated_memory[i].used != 1) { // Should never happen
  186.                 mem->stats.invalid_frees++;
  187.             } else {
  188.                 mem->mallocated_memory[i].used = 0;
  189.                 mem->config.used_blocks--;
  190.             }
  191.  
  192.             // No clearing, next malloc clears, if needed
  193.             for(int o = mem->mallocated_memory[i].sz; o < mem->MALLOC_MEM_BLOCK_SIZE; o++) {
  194.                 if(mem->mallocated_memory[i].memory[o] != 0){
  195.                     mem->stats.writes_beyond++;
  196.                 }
  197.             }
  198.             for(int o = 0; o < mem->MALLOC_MEM_BLOCK_COUNT_PRE; o++) {
  199.                 if(mem->mallocated_memory[i].memoryPre[o] != 0){
  200.                     mem->stats.writes_before++;
  201.                 }
  202.             }
  203.             for(int o = 0; o < mem->MALLOC_MEM_BLOCK_COUNT_POST; o++) {
  204.                 if(mem->mallocated_memory[i].memoryPost[o] != 0){
  205.                     mem->stats.writes_beyond++;
  206.                 }
  207.             }
  208.  
  209.             return;
  210.         }
  211.  
  212.     }
  213.     // No our memory, freeing whatever bad
  214.     mem->stats.invalid_frees++;
  215. }
  216.  
  217. void* calloc(unsigned int num, unsigned int sz) {
  218.     struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  219.     return mem->functions.malloc(num*sz);
  220. }
  221.  
  222. void* realloc(void* ptr, unsigned int sz) {
  223.     struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  224.  
  225.     // Find the memory
  226.     for(int i = 0; i < mem->config.last_init_block; i++) {
  227.         if((&(mem->mallocated_memory[i].memory)) == ptr) { // Our memory
  228.             if (mem->mallocated_memory[i].used != 1) { // Should never happen
  229.                 mem->stats.invalid_realloc++;
  230.                 return 0;
  231.             } else {
  232.  
  233.                 // Check for corruptions before extending. Twice the severity, twice the errors
  234.                 for(int o = mem->mallocated_memory[i].sz; o < mem->MALLOC_MEM_BLOCK_SIZE; o++) {
  235.                     if(mem->mallocated_memory[i].memory[o] != 0){
  236.                         mem->stats.invalid_realloc++;
  237.                         mem->stats.writes_beyond++;
  238.                     }
  239.                 }
  240.  
  241.                 for(int o = 0; o < mem->MALLOC_MEM_BLOCK_COUNT_PRE; o++) {
  242.                     if(mem->mallocated_memory[i].memoryPre[o] != 0){
  243.                         mem->stats.invalid_realloc++;
  244.                         mem->stats.writes_before++;
  245.                     }
  246.                 }
  247.  
  248.                 for(int o = 0; o < mem->MALLOC_MEM_BLOCK_COUNT_POST; o++) {
  249.                     if(mem->mallocated_memory[i].memoryPost[o] != 0){
  250.                         mem->stats.invalid_realloc++;
  251.                         mem->stats.writes_beyond++;
  252.                     }
  253.                 }
  254.  
  255.                 // No corruptions, check for size
  256.                 if(sz > (unsigned int) mem->MALLOC_MEM_BLOCK_SIZE) {
  257.                     mem->stats.big_allocs++;
  258.                     return 0;
  259.                 } else if( ((int)sz) < 0) {
  260.                     mem->stats.negative_allocs++;
  261.                     return 0;
  262.                 } else if(sz == 0) {
  263.                     mem->stats.zero_allocs++;
  264.                     return 0;
  265.                 }
  266.  
  267.                 if (mem->mallocated_memory[i].sz < sz) { // Trimming -> zero fill the extension
  268.                     for(unsigned int o = sz; o < mem->mallocated_memory[i].sz; o++) {
  269.                         mem->mallocated_memory[i].memory[o] = 0;
  270.                     }
  271.                 }
  272.                 mem->mallocated_memory[i].sz = sz;
  273.                 return &(mem->mallocated_memory[i].memory);
  274.             }
  275.         }
  276.     }
  277.  
  278.     mem->stats.invalid_realloc++;
  279.     return 0;
  280. }
  281.  
  282. void* aligned_alloc(unsigned int alignment, unsigned int sz) {
  283.     struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  284.     if(sz % alignment > 0) {
  285.         mem->stats.negative_allocs++;
  286.         return 0;
  287.     }
  288.  
  289.     // lol, no
  290.     return mem->functions.malloc(sz);
  291. }
  292.  
  293. void init_memory_%RANDOM%() {
  294.     // No memset
  295.     char* data = (char*) &memory_%RANDOM%;
  296.     for(unsigned int i = 0; i < sizeof(struct t_memory_%RANDOM%); i++) {
  297.         data[i] = 0;
  298.     }
  299.  
  300.     struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  301.     mem->MALLOC_MEM_BLOCK_COUNT = MALLOC_MEM_BLOCK_COUNT_%RANDOM%;
  302.     mem->MALLOC_MEM_BLOCK_SIZE = MALLOC_MEM_BLOCK_SIZE_%RANDOM%;
  303.     mem->MALLOC_MEM_BLOCK_COUNT_PRE = MALLOC_MEM_BLOCK_COUNT_PRE_%RANDOM%;
  304.     mem->MALLOC_MEM_BLOCK_COUNT_POST = MALLOC_MEM_BLOCK_COUNT_POST_%RANDOM%;
  305.  
  306.     mem->functions.init_memory = &init_memory_%RANDOM%;
  307.     mem->functions.check_memory_after_end = &check_memory_after_end_%RANDOM%;
  308.     mem->functions.malloc_init_block = &malloc_init_block_%RANDOM%;
  309.     mem->functions.malloc = &malloc;
  310.     mem->functions.aligned_alloc = &aligned_alloc;
  311.     mem->functions.realloc = &realloc;
  312.     mem->functions.calloc = &calloc;
  313.     mem->functions.free = &free;
  314.  
  315.     mem->userMain = &main;
  316. }
  317.  
  318. #ifdef main
  319. #undef main
  320. #endif
  321.  
  322. // The real entry point
  323. int main(int argc, char** argv) {
  324.  
  325.     // Init the memory
  326.     init_memory_%RANDOM%();
  327.      struct t_memory_%RANDOM%* mem = &memory_%RANDOM%;
  328.  
  329.     // Segfault by default
  330.     int result = -1;
  331.  
  332.  
  333.     if(argc >= 2) {
  334.  
  335.         // Read total number of allocations available
  336.         if(mem->config.available_allocations < 0) {
  337.             mem->config.available_allocations = mem->MALLOC_MEM_BLOCK_COUNT;
  338.         }
  339.  
  340.         int argAllocations = 0;
  341.         int sign = 1;
  342.         for(int i = 0; argv[1][i] != '\0';i++){
  343.             char c = argv[1][i];
  344.             if(c >= '0' && c <= '9') {
  345.                 argAllocations *= 10;
  346.                 argAllocations += c - '0';
  347.             } else if (c == '-') { // ... but why?
  348.                 sign = -1;
  349.             }
  350.         }
  351.  
  352.         // And add the one we are about to do
  353.         argAllocations++;
  354.         mem->config.available_allocations = argAllocations * sign;
  355.  
  356.         // Create new argv base on the original one without the first argument
  357.         char** anotherArgv = (char**) malloc(sizeof(char*) * (argc - 1));
  358.  
  359.         // Copy file name
  360.         anotherArgv[0] = argv[0];
  361.  
  362.         // And every argument after that
  363.         for(int i = 2; i < argc; i++) {
  364.             anotherArgv[i-1] = argv[i];
  365.         }
  366.  
  367.         // Call user main
  368.         result = mem->userMain(argc-1, anotherArgv);
  369.  
  370.         // Destroy our allocated argv
  371.         free(anotherArgv);
  372.  
  373.         // Check memory for errors
  374.         mem->functions.check_memory_after_end();
  375.  
  376.         return result;
  377.     }
  378.  
  379.     return result;
  380. }
  381.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement