exercise_7_2.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. (Advanced) Implement malloc() and free()
  3. */
  4. // TODO: puts use malloc why?
  5. // TODO: more tests more implementations
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <stdint.h>
  11. #include <stddef.h>
  12. #include <assert.h>
  13. #ifndef CHUNK_SIZE
  14. #define CHUNK_SIZE 100
  15. #endif
  16. struct free_list_node
  17. {
  18. size_t length;
  19. struct free_list_node* prev_free;
  20. struct free_list_node* next_free;
  21. };
  22. struct free_list_node *head;
  23. static void
  24. debug_brk(void)
  25. {
  26. char buffer[200];
  27. snprintf(buffer, 200, "current program break: %p\n", sbrk(0));
  28. write(STDOUT_FILENO, buffer, strlen(buffer));
  29. }
  30. static void
  31. debug_pointer(void *ptr)
  32. {
  33. char buffer[200];
  34. snprintf(buffer, 200, "%p\n", ptr);
  35. write(STDOUT_FILENO, buffer, strlen(buffer));
  36. }
  37. static void
  38. debug_print_free_list()
  39. {
  40. char buffer[200];
  41. write(STDOUT_FILENO, "free_list:\n", 11);
  42. for (struct free_list_node *node = head;
  43. node; node = node->next_free)
  44. {
  45. snprintf(buffer, 200, "\t node: %p, %zu\n", head, head->length);
  46. write(STDOUT_FILENO, buffer, strlen(buffer));
  47. }
  48. write(STDOUT_FILENO, "\n", 1);
  49. }
  50. static struct free_list_node*
  51. find_space_to_allocate(size_t size)
  52. {
  53. struct free_list_node *result = NULL;
  54. for (struct free_list_node *node = head; node; node = node->next_free)
  55. if (node->length >= size)
  56. result = node;
  57. return result;
  58. }
  59. void*
  60. malloc(size_t size)
  61. {
  62. size_t real_size = size + sizeof(size_t);
  63. void* malloced_memory = NULL;
  64. char buffer[200];
  65. write(STDOUT_FILENO, "inside malloc\n", 14);
  66. if (!head)
  67. {
  68. write(STDOUT_FILENO, "brand new malloc\n", 17);
  69. debug_brk();
  70. void* program_break = sbrk(CHUNK_SIZE);
  71. debug_brk();
  72. head = program_break;
  73. head->length = CHUNK_SIZE;
  74. head->prev_free = NULL;
  75. head->next_free = NULL;
  76. }
  77. debug_print_free_list();
  78. struct free_list_node *node_to_allocate;
  79. if ((node_to_allocate = find_space_to_allocate(real_size)) != NULL)
  80. {
  81. void *new_node_ptr = (char *)head + real_size;
  82. memmove(new_node_ptr, head, sizeof *head);
  83. *(size_t*)head = size;
  84. malloced_memory = head;
  85. *(size_t *) malloced_memory = size;
  86. malloced_memory = (size_t *)malloced_memory + 1;
  87. head = new_node_ptr;
  88. head->length -= real_size;
  89. }
  90. debug_print_free_list();
  91. return malloced_memory;
  92. }
  93. static struct free_list_node*
  94. find_nearest_free_space(void* ptr)
  95. {
  96. struct free_list_node *result = head;
  97. for (struct free_list_node *node = head; node; node = node->next_free)
  98. {
  99. ptrdiff_t best_result = abs(ptr - (void*)result);
  100. ptrdiff_t current_result = abs(ptr - (void*)node);
  101. if (best_result < current_result)
  102. result = node;
  103. }
  104. return result;
  105. }
  106. void
  107. free(void* ptr)
  108. {
  109. typedef struct free_list_node free_list_node;
  110. write(STDOUT_FILENO, "inside free\n", 12);
  111. size_t* malloced_size = (size_t*)ptr - 1;
  112. struct free_list_node* closest_node = find_nearest_free_space(malloced_size);
  113. if ((void*)malloced_size < (void*)closest_node)
  114. {
  115. closest_node->length += *malloced_size + sizeof(size_t);
  116. memmove(malloced_size, closest_node, sizeof *closest_node);
  117. if (closest_node == head) head = (free_list_node *)malloced_size;
  118. closest_node = (free_list_node *)malloced_size;
  119. if (closest_node->next_free)
  120. closest_node->next_free->prev_free = closest_node;
  121. if (closest_node->prev_free)
  122. closest_node->prev_free->next_free = closest_node;
  123. }
  124. else
  125. {
  126. closest_node->length += *malloced_size + sizeof(size_t);
  127. }
  128. debug_print_free_list();
  129. }
  130. /*
  131. * tst
  132. */
  133. static void
  134. tst_simple_malloc(void)
  135. {
  136. unsigned char *arr = malloc(10);
  137. assert(*((size_t *)arr - 1) == 10);
  138. debug_pointer(arr);
  139. free(arr);
  140. }
  141. int
  142. main(int argc, char *argv[])
  143. {
  144. tst_simple_malloc();
  145. return EXIT_SUCCESS;
  146. }