feat: working wf
This commit is contained in:
239
labs/cs2106/labs/lab4/linkedlist/llist.c
Normal file
239
labs/cs2106/labs/lab4/linkedlist/llist.c
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "llist.h"
|
||||||
|
|
||||||
|
//#define DEBUG // Enable debug printing
|
||||||
|
|
||||||
|
// Debug printer
|
||||||
|
|
||||||
|
void dbprintf(char *format, ...) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
vprintf(format, args);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements a double linked list.
|
||||||
|
|
||||||
|
// Create a new node. You need to
|
||||||
|
// Create your own TData node, populate
|
||||||
|
// it, then create a new node with a suitable
|
||||||
|
// key. Insertion into the link list is
|
||||||
|
// by ascending order of the key. An example key
|
||||||
|
// might be the starting address of a memory segment.
|
||||||
|
|
||||||
|
TNode *make_node(unsigned int key, TData *data) {
|
||||||
|
TNode *node = malloc(sizeof(TNode));
|
||||||
|
node->key = key;
|
||||||
|
node->pdata = data;
|
||||||
|
node->prev = NULL;
|
||||||
|
node->next = NULL;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inserts a node into the correct point of the
|
||||||
|
// double linked list. The list is sorted
|
||||||
|
// in ascending order of the key. Duplicate keys
|
||||||
|
// are permitted, though not recommended.
|
||||||
|
// llist = Pointer to link list
|
||||||
|
// node = Pointer to node created by make_node
|
||||||
|
// dir = 0: Insert in ascending order
|
||||||
|
// dir = 1: Insert in descending order
|
||||||
|
|
||||||
|
void insert_node(TNode **llist, TNode *node, int dir) {
|
||||||
|
if(*llist == NULL) {
|
||||||
|
*llist = node;
|
||||||
|
(*llist)->trav = *llist;
|
||||||
|
(*llist)->tail = *llist;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(((*llist)->key >= node->key && dir == 0) || (((*llist)->key <= node->key) && dir == 1)) {
|
||||||
|
node->next = *llist;
|
||||||
|
(*llist)->prev = node;
|
||||||
|
*llist = node;
|
||||||
|
(*llist)->trav = *llist;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TNode *trav = *llist;
|
||||||
|
|
||||||
|
if(dir == 0)
|
||||||
|
while(trav->next != NULL && trav->key < node->key)
|
||||||
|
trav = trav->next;
|
||||||
|
else if(dir == 1)
|
||||||
|
while(trav->next != NULL && trav->key > node->key)
|
||||||
|
trav = trav->next;
|
||||||
|
|
||||||
|
if(trav->next == NULL && ((trav->key < node->key && dir == 0) ||
|
||||||
|
(trav->key > node->key && dir == 1))) {
|
||||||
|
trav->next = node;
|
||||||
|
node->prev = trav;
|
||||||
|
|
||||||
|
// Set the tail
|
||||||
|
(*llist)->tail = node;
|
||||||
|
} else {
|
||||||
|
// Insert into the previous space
|
||||||
|
|
||||||
|
node->next = trav;
|
||||||
|
|
||||||
|
if(trav->prev != NULL) {
|
||||||
|
trav->prev->next = node;
|
||||||
|
node->prev = trav->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trav->next != NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
trav->prev = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a given node from the linked list
|
||||||
|
void delete_node(TNode **llist, TNode *node) {
|
||||||
|
|
||||||
|
if(*llist == NULL || node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if((*llist)->key == node->key) {
|
||||||
|
// Node to be deleted is at the front of the list.
|
||||||
|
*llist = (*llist)->next;
|
||||||
|
|
||||||
|
// Ensure that we don't point to it anymore.
|
||||||
|
if(*llist != NULL)
|
||||||
|
(*llist)->prev = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TNode *trav = *llist;
|
||||||
|
|
||||||
|
while(trav != NULL && trav->key != node->key)
|
||||||
|
trav = trav->next;
|
||||||
|
|
||||||
|
// We've found the deletion point
|
||||||
|
if(trav != NULL) {
|
||||||
|
trav->prev->next = trav->next;
|
||||||
|
|
||||||
|
if(trav->next != NULL)
|
||||||
|
trav->next->prev = trav->prev;
|
||||||
|
else
|
||||||
|
(*llist)->tail = trav->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a node that has the value of key
|
||||||
|
// If there are duplicate keys, the first one encountered
|
||||||
|
// will be returned.
|
||||||
|
TNode *find_node(TNode *llist, unsigned int key) {
|
||||||
|
if(llist == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
TNode *trav = llist;
|
||||||
|
|
||||||
|
while(trav != NULL && trav->key != key)
|
||||||
|
trav = trav->next;
|
||||||
|
|
||||||
|
return trav;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge the node provided with either the node after or the node before.
|
||||||
|
// You need to manage merging the data in node->pdata yourself. This code just
|
||||||
|
// deletes the larger of the two nodes.
|
||||||
|
// dir = 0: Merge with node before
|
||||||
|
// dir = 1: Merge with node after
|
||||||
|
|
||||||
|
void merge_node(TNode *llist, TNode *node, int dir) {
|
||||||
|
if(dir == 0) {
|
||||||
|
if(node->prev == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete_node(&llist, node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(dir == 1) {
|
||||||
|
if(node->next == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete_node(&llist, node->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go over every element of llist, and call func
|
||||||
|
// func prototype is void func(TNode *);
|
||||||
|
|
||||||
|
void process_list(TNode *llist, void (*func)(TNode *)) {
|
||||||
|
TNode *trav = llist;
|
||||||
|
while(trav) {
|
||||||
|
func(trav);
|
||||||
|
trav = trav->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Purge the entire list. You must
|
||||||
|
// free any dynamic data in the TData
|
||||||
|
// struct yourself.
|
||||||
|
void purge_list(TNode **llist) {
|
||||||
|
TNode *trav = *llist, *tmp;
|
||||||
|
while(trav) {
|
||||||
|
tmp = trav->next;
|
||||||
|
free(trav);
|
||||||
|
trav = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
*llist = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reset traverser
|
||||||
|
// where=0 START: Resets traverser to start of list
|
||||||
|
// where=1 END: Rsets
|
||||||
|
void reset_traverser(TNode *llist, int where)
|
||||||
|
{
|
||||||
|
if(llist == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(where == FRONT)
|
||||||
|
llist->trav = llist;
|
||||||
|
else
|
||||||
|
if(where == REAR)
|
||||||
|
llist->trav = llist->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next node
|
||||||
|
TNode *succ(TNode *llist)
|
||||||
|
{
|
||||||
|
if(llist == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
TNode *ret = llist->trav;
|
||||||
|
|
||||||
|
if(llist->trav != NULL)
|
||||||
|
llist->trav = llist->trav->next;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the previous node
|
||||||
|
TNode *pred(TNode *llist)
|
||||||
|
{
|
||||||
|
if(llist == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
TNode *ret = llist->trav;
|
||||||
|
|
||||||
|
if(llist->trav != NULL)
|
||||||
|
llist->trav = llist->trav->prev;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
114
labs/cs2106/labs/lab4/linkedlist/llist.h
Normal file
114
labs/cs2106/labs/lab4/linkedlist/llist.h
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
// Uncomment the next line to enable debug printing
|
||||||
|
#define DEBUG // Enable debug printing
|
||||||
|
|
||||||
|
// The debug printer; used like a normal printf, except
|
||||||
|
// that printing can be turned off by commenting out the
|
||||||
|
// #define DEBUG above.
|
||||||
|
void dbprintf(char *format, ...);
|
||||||
|
|
||||||
|
// You should modify this structure to hold
|
||||||
|
// whatever you need to implement your
|
||||||
|
// memory manager. You can delete the
|
||||||
|
// val field. It is only used for testlist.c
|
||||||
|
|
||||||
|
typedef struct td {
|
||||||
|
int val;
|
||||||
|
} TData;
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------
|
||||||
|
BASIC ROUTINES
|
||||||
|
|
||||||
|
Basic linked list routines
|
||||||
|
|
||||||
|
---------------------------------------- */
|
||||||
|
|
||||||
|
// Basic double linked list node.
|
||||||
|
|
||||||
|
typedef struct tn {
|
||||||
|
unsigned int key;
|
||||||
|
TData *pdata; // Pointer to the data you want to store
|
||||||
|
|
||||||
|
struct tn *trav; // Only used in the root for traversal
|
||||||
|
struct tn *tail; // Only used in the root for finding the end of the list
|
||||||
|
struct tn *prev;
|
||||||
|
struct tn *next;
|
||||||
|
} TNode;
|
||||||
|
|
||||||
|
// Insert Direction
|
||||||
|
#define ASCENDING 0
|
||||||
|
#define DESCENDING 1
|
||||||
|
|
||||||
|
// Merge direction
|
||||||
|
#define PRECEDING 0
|
||||||
|
#define SUCCEEDING 1
|
||||||
|
|
||||||
|
// Traverser position
|
||||||
|
#define FRONT 0
|
||||||
|
#define REAR 1
|
||||||
|
|
||||||
|
// Create a new node. You need to
|
||||||
|
// Create your own TData node, populate
|
||||||
|
// it, then create a new node with a suitable
|
||||||
|
// key. Insertion into the link list is
|
||||||
|
// by ascending order of the key. An example key
|
||||||
|
// might be the starting address of a memory segment.
|
||||||
|
|
||||||
|
TNode *make_node(unsigned int key, TData *data);
|
||||||
|
|
||||||
|
// Inserts a node into the correct point of the
|
||||||
|
// double linked list. The list is sorted
|
||||||
|
// in ascending order of the key. Duplicate keys
|
||||||
|
// are permitted, though not recommended.
|
||||||
|
// llist = Pointer to link list
|
||||||
|
// node = Pointer to node created by make_node
|
||||||
|
// dir = 0: Insert in ascending order
|
||||||
|
// dir = 1: Insert in descending order
|
||||||
|
|
||||||
|
void insert_node(TNode **llist, TNode *node, int dir);
|
||||||
|
|
||||||
|
|
||||||
|
// Remove a given node from the linked list
|
||||||
|
void delete_node(TNode **llist, TNode *node);
|
||||||
|
|
||||||
|
// Find a node that has the value of key
|
||||||
|
// If there are duplicate keys, the first one encountered
|
||||||
|
// will be returned.
|
||||||
|
TNode *find_node(TNode *llist, unsigned int key);
|
||||||
|
|
||||||
|
// Merge the node provided with either the node after or the node before.
|
||||||
|
// You need to manage merging the data in node->pdata yourself. This code just
|
||||||
|
// deletes the larger of the two nodes.
|
||||||
|
// dir = 0: Merge with node before
|
||||||
|
// dir = 1: Merge with node after
|
||||||
|
|
||||||
|
void merge_node(TNode *llist, TNode *node, int dir);
|
||||||
|
|
||||||
|
// Purge the entire list. You must
|
||||||
|
// free any dynamic data in the TData
|
||||||
|
// struct yourself.
|
||||||
|
void purge_list(TNode **llist);
|
||||||
|
|
||||||
|
/* -----------------------------------------
|
||||||
|
TRAVERSAL ROUTINES
|
||||||
|
|
||||||
|
Lets you traverse the linked list
|
||||||
|
|
||||||
|
---------------------------------------- */
|
||||||
|
|
||||||
|
// Go over every element of llist, and call func
|
||||||
|
// func prototype is void func(TNode *);
|
||||||
|
|
||||||
|
void process_list(TNode *llist, void (*func)(TNode *));
|
||||||
|
|
||||||
|
// Reset traverser
|
||||||
|
// where=0 START: Resets traverser to start of list
|
||||||
|
// where=1 END: Rsets
|
||||||
|
void reset_traverser(TNode *llist, int where);
|
||||||
|
|
||||||
|
// Get the next node
|
||||||
|
TNode *succ(TNode *llist);
|
||||||
|
|
||||||
|
// Get the previous node
|
||||||
|
TNode *pred(TNode *llist);
|
||||||
25
labs/cs2106/labs/lab4/linkedlist/mymalloc.c
Normal file
25
labs/cs2106/labs/lab4/linkedlist/mymalloc.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "mymalloc.h"
|
||||||
|
|
||||||
|
char _heap[MEMSIZE] = {0};
|
||||||
|
TNode *_memlist = NULL; // To maintain information about length
|
||||||
|
|
||||||
|
// Do not change this. Used by the test harness.
|
||||||
|
// You may however use this function in your code if necessary.
|
||||||
|
long get_index(void *ptr) {
|
||||||
|
if(ptr == NULL)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return (long) ((char *) ptr - &_heap[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocates size bytes of memory and returns a pointer
|
||||||
|
// to the first byte.
|
||||||
|
void *mymalloc(size_t size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees memory pointer to by ptr.
|
||||||
|
void myfree(void *ptr) {
|
||||||
|
}
|
||||||
|
|
||||||
5
labs/cs2106/labs/lab4/linkedlist/mymalloc.h
Normal file
5
labs/cs2106/labs/lab4/linkedlist/mymalloc.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#define MEMSIZE 64 * 1024 // Size of memory in bytes
|
||||||
|
|
||||||
|
long get_index(void *ptr);
|
||||||
|
void *mymalloc(size_t);
|
||||||
|
void myfree(void *);
|
||||||
178
labs/cs2106/labs/lab4/linkedlist/testlist.c
Normal file
178
labs/cs2106/labs/lab4/linkedlist/testlist.c
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "llist.h"
|
||||||
|
|
||||||
|
#define COUNT 10
|
||||||
|
|
||||||
|
void print_node(TNode *node) {
|
||||||
|
if(node != NULL)
|
||||||
|
printf("Key: %d\n", node->key);
|
||||||
|
else
|
||||||
|
printf("Unable to find key.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_data(TNode *node) {
|
||||||
|
free(node->pdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void trav_list(TNode *llist) {
|
||||||
|
reset_traverser(llist, FRONT);
|
||||||
|
TNode *node;
|
||||||
|
|
||||||
|
do {
|
||||||
|
node = succ(llist);
|
||||||
|
if(node)
|
||||||
|
print_node(node);
|
||||||
|
} while(node != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rev_trav_list(TNode *llist) {
|
||||||
|
reset_traverser(llist, REAR);
|
||||||
|
TNode *node;
|
||||||
|
|
||||||
|
do{
|
||||||
|
node = pred(llist);
|
||||||
|
if(node)
|
||||||
|
print_node(node);
|
||||||
|
} while(node != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
TNode *llist = NULL;
|
||||||
|
|
||||||
|
int test_array[COUNT] = {10, 6, 2, 8, 1, 4, 5, 3, 9, 7};
|
||||||
|
|
||||||
|
// Insert
|
||||||
|
|
||||||
|
char c;
|
||||||
|
printf("Hit enter to start ascending order test\n");
|
||||||
|
scanf("%c", &c);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
printf("Inserting in ascending order\n");
|
||||||
|
TData *data;
|
||||||
|
TNode *node;
|
||||||
|
|
||||||
|
for(i=0; i<COUNT; i++) {
|
||||||
|
data = (TData *) malloc(sizeof(TData));
|
||||||
|
data->val = test_array[i];
|
||||||
|
node = make_node(test_array[i], data);
|
||||||
|
insert_node(&llist, node, ASCENDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Printing entire list\n");
|
||||||
|
process_list(llist, print_node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Printing entire list using reverse traversal\n");
|
||||||
|
rev_trav_list(llist);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Searching for 2\n");
|
||||||
|
node = find_node(llist, 2);
|
||||||
|
print_node(node);
|
||||||
|
|
||||||
|
printf("Deleting node 2\n");
|
||||||
|
delete_node(&llist, node);
|
||||||
|
|
||||||
|
printf("Searching for 2\n");
|
||||||
|
node = find_node(llist, 2);
|
||||||
|
print_node(node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Searching for 5\n");
|
||||||
|
node = find_node(llist, 5);
|
||||||
|
print_node(node);
|
||||||
|
|
||||||
|
printf("Deleting node 5\n");
|
||||||
|
delete_node(&llist, node);
|
||||||
|
|
||||||
|
printf("Searching for 5\n");
|
||||||
|
node = find_node(llist, 5);
|
||||||
|
print_node(node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Searching for 22\n");
|
||||||
|
node = find_node(llist, 22);
|
||||||
|
print_node(node);
|
||||||
|
|
||||||
|
printf("Deleting node 22\n");
|
||||||
|
delete_node(&llist, node);
|
||||||
|
|
||||||
|
printf("Searching for 22\n");
|
||||||
|
node = find_node(llist, 22);
|
||||||
|
print_node(node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Purging list\n");
|
||||||
|
process_list(llist, free_data);
|
||||||
|
purge_list(&llist);
|
||||||
|
|
||||||
|
printf("Printing entire list\n");
|
||||||
|
process_list(llist, print_node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Hit enter to start descending order test\n");
|
||||||
|
scanf("%c", &c);
|
||||||
|
|
||||||
|
printf("Inserting in descending order\n");
|
||||||
|
for(i=0; i<COUNT; i++) {
|
||||||
|
TNode *node = make_node(test_array[i], NULL);
|
||||||
|
insert_node(&llist, node, DESCENDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Printing entire list\n");
|
||||||
|
process_list(llist, print_node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Printing entire list using reverse traversal\n");
|
||||||
|
rev_trav_list(llist);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Searching for 2\n");
|
||||||
|
node = find_node(llist, 2);
|
||||||
|
print_node(node);
|
||||||
|
|
||||||
|
printf("Deleting node 2\n");
|
||||||
|
delete_node(&llist, node);
|
||||||
|
|
||||||
|
printf("Searching for 2\n");
|
||||||
|
node = find_node(llist, 2);
|
||||||
|
print_node(node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Searching for 5\n");
|
||||||
|
node = find_node(llist, 5);
|
||||||
|
print_node(node);
|
||||||
|
|
||||||
|
printf("Deleting node 5\n");
|
||||||
|
delete_node(&llist, node);
|
||||||
|
|
||||||
|
printf("Searching for 5\n");
|
||||||
|
node = find_node(llist, 5);
|
||||||
|
print_node(node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Searching for 22\n");
|
||||||
|
node = find_node(llist, 22);
|
||||||
|
print_node(node);
|
||||||
|
|
||||||
|
printf("Deleting node 22\n");
|
||||||
|
delete_node(&llist, node);
|
||||||
|
|
||||||
|
printf("Searching for 22\n");
|
||||||
|
node = find_node(llist, 22);
|
||||||
|
print_node(node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Purging list\n");
|
||||||
|
process_list(llist, free_data);
|
||||||
|
purge_list(&llist);
|
||||||
|
|
||||||
|
printf("Printing entire list\n");
|
||||||
|
process_list(llist, print_node);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
}
|
||||||
36
labs/cs2106/labs/lab4/linkedlist/testmalloc.c
Normal file
36
labs/cs2106/labs/lab4/linkedlist/testmalloc.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "mymalloc.h"
|
||||||
|
|
||||||
|
void testalloc(long size, char *ptrname, char **ptr) {
|
||||||
|
printf("\nAllocating %ld bytes to %s\n", size, ptrname);
|
||||||
|
*ptr = mymalloc(size);
|
||||||
|
|
||||||
|
if(*ptr == NULL)
|
||||||
|
printf("Allocation failed.\n");
|
||||||
|
print_memlist();
|
||||||
|
}
|
||||||
|
|
||||||
|
void testfree(char *ptr, char *ptrname) {
|
||||||
|
printf("\nFreeing %s\n", ptrname);
|
||||||
|
myfree(ptr);
|
||||||
|
print_memlist();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
|
||||||
|
|
||||||
|
testalloc(2048, "ptr1", &ptr1);
|
||||||
|
testalloc(6144, "ptr2", &ptr2);
|
||||||
|
testalloc(1024, "ptr3", &ptr3);
|
||||||
|
testfree(ptr2, "ptr2");
|
||||||
|
testalloc(2048, "ptr2", &ptr2);
|
||||||
|
testalloc(4096, "ptr4", &ptr4);
|
||||||
|
testfree(ptr2, "ptr2");
|
||||||
|
testalloc(3072, "ptr5", &ptr5);
|
||||||
|
testfree(ptr1, "ptr1");
|
||||||
|
testfree(ptr2, "ptr2");
|
||||||
|
testfree(ptr3, "ptr3");
|
||||||
|
testfree(ptr4, "ptr4");
|
||||||
|
testfree(ptr5, "ptr5");
|
||||||
|
|
||||||
|
}
|
||||||
13
labs/cs2106/labs/lab4/linkedlist/wf/Makefile
Normal file
13
labs/cs2106/labs/lab4/linkedlist/wf/Makefile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.PHONY: run test
|
||||||
|
|
||||||
|
run: harness-wf
|
||||||
|
./harness-wf
|
||||||
|
|
||||||
|
test: testmalloc
|
||||||
|
./testmalloc
|
||||||
|
|
||||||
|
harness-wf: harness-wf.c llist.c mymalloc.c
|
||||||
|
gcc $^ -o $@
|
||||||
|
|
||||||
|
testmalloc: testmalloc.c mymalloc.c llist.c
|
||||||
|
gcc $^ -o $@
|
||||||
55
labs/cs2106/labs/lab4/linkedlist/wf/harness-wf.c
Normal file
55
labs/cs2106/labs/lab4/linkedlist/wf/harness-wf.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "mymalloc.h"
|
||||||
|
|
||||||
|
void *runmalloc(size_t len, long expected_ndx) {
|
||||||
|
|
||||||
|
long ndx;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
printf("Allocate %ld bytes.\n", len);
|
||||||
|
printf("Before: ");
|
||||||
|
print_memlist();
|
||||||
|
printf("\n");
|
||||||
|
ptr = mymalloc(len);
|
||||||
|
ndx = get_index((void *) ptr);
|
||||||
|
printf("EXPECTED: %ld ACTUAL: %ld\n", expected_ndx, ndx);
|
||||||
|
printf("After: ");
|
||||||
|
print_memlist();
|
||||||
|
printf("\n");
|
||||||
|
assert(ndx == expected_ndx);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void runfree(void *ptr) {
|
||||||
|
printf("Free\n");
|
||||||
|
printf("Before: ");
|
||||||
|
print_memlist();
|
||||||
|
printf("\n");
|
||||||
|
myfree(ptr);
|
||||||
|
printf("After: ");
|
||||||
|
print_memlist();
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
|
||||||
|
|
||||||
|
ptr1 = runmalloc(4, 0);
|
||||||
|
ptr2 = runmalloc(32, 4);
|
||||||
|
ptr3 = runmalloc(2, 36);
|
||||||
|
runfree(ptr2);
|
||||||
|
ptr2 = runmalloc(12, 38);
|
||||||
|
ptr4 = runmalloc(24, 50);
|
||||||
|
ptr5 = runmalloc(18, 74);
|
||||||
|
runfree(ptr1);
|
||||||
|
ptr1 = runmalloc(2, 92);
|
||||||
|
runfree(ptr1);
|
||||||
|
runfree(ptr2);
|
||||||
|
runfree(ptr3);
|
||||||
|
runfree(ptr4);
|
||||||
|
runfree(ptr5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
239
labs/cs2106/labs/lab4/linkedlist/wf/llist.c
Normal file
239
labs/cs2106/labs/lab4/linkedlist/wf/llist.c
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "llist.h"
|
||||||
|
|
||||||
|
//#define DEBUG // Enable debug printing
|
||||||
|
|
||||||
|
// Debug printer
|
||||||
|
|
||||||
|
void dbprintf(char *format, ...) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
vprintf(format, args);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements a double linked list.
|
||||||
|
|
||||||
|
// Create a new node. You need to
|
||||||
|
// Create your own TData node, populate
|
||||||
|
// it, then create a new node with a suitable
|
||||||
|
// key. Insertion into the link list is
|
||||||
|
// by ascending order of the key. An example key
|
||||||
|
// might be the starting address of a memory segment.
|
||||||
|
|
||||||
|
TNode *make_node(unsigned int key, TData *data) {
|
||||||
|
TNode *node = malloc(sizeof(TNode));
|
||||||
|
node->key = key;
|
||||||
|
node->pdata = data;
|
||||||
|
node->prev = NULL;
|
||||||
|
node->next = NULL;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inserts a node into the correct point of the
|
||||||
|
// double linked list. The list is sorted
|
||||||
|
// in ascending order of the key. Duplicate keys
|
||||||
|
// are permitted, though not recommended.
|
||||||
|
// llist = Pointer to link list
|
||||||
|
// node = Pointer to node created by make_node
|
||||||
|
// dir = 0: Insert in ascending order
|
||||||
|
// dir = 1: Insert in descending order
|
||||||
|
|
||||||
|
void insert_node(TNode **llist, TNode *node, int dir) {
|
||||||
|
if(*llist == NULL) {
|
||||||
|
*llist = node;
|
||||||
|
(*llist)->trav = *llist;
|
||||||
|
(*llist)->tail = *llist;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(((*llist)->key >= node->key && dir == 0) || (((*llist)->key <= node->key) && dir == 1)) {
|
||||||
|
node->next = *llist;
|
||||||
|
(*llist)->prev = node;
|
||||||
|
*llist = node;
|
||||||
|
(*llist)->trav = *llist;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TNode *trav = *llist;
|
||||||
|
|
||||||
|
if(dir == 0)
|
||||||
|
while(trav->next != NULL && trav->key < node->key)
|
||||||
|
trav = trav->next;
|
||||||
|
else if(dir == 1)
|
||||||
|
while(trav->next != NULL && trav->key > node->key)
|
||||||
|
trav = trav->next;
|
||||||
|
|
||||||
|
if(trav->next == NULL && ((trav->key < node->key && dir == 0) ||
|
||||||
|
(trav->key > node->key && dir == 1))) {
|
||||||
|
trav->next = node;
|
||||||
|
node->prev = trav;
|
||||||
|
|
||||||
|
// Set the tail
|
||||||
|
(*llist)->tail = node;
|
||||||
|
} else {
|
||||||
|
// Insert into the previous space
|
||||||
|
|
||||||
|
node->next = trav;
|
||||||
|
|
||||||
|
if(trav->prev != NULL) {
|
||||||
|
trav->prev->next = node;
|
||||||
|
node->prev = trav->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trav->next != NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
trav->prev = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a given node from the linked list
|
||||||
|
void delete_node(TNode **llist, TNode *node) {
|
||||||
|
|
||||||
|
if(*llist == NULL || node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if((*llist)->key == node->key) {
|
||||||
|
// Node to be deleted is at the front of the list.
|
||||||
|
*llist = (*llist)->next;
|
||||||
|
|
||||||
|
// Ensure that we don't point to it anymore.
|
||||||
|
if(*llist != NULL)
|
||||||
|
(*llist)->prev = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TNode *trav = *llist;
|
||||||
|
|
||||||
|
while(trav != NULL && trav->key != node->key)
|
||||||
|
trav = trav->next;
|
||||||
|
|
||||||
|
// We've found the deletion point
|
||||||
|
if(trav != NULL) {
|
||||||
|
trav->prev->next = trav->next;
|
||||||
|
|
||||||
|
if(trav->next != NULL)
|
||||||
|
trav->next->prev = trav->prev;
|
||||||
|
else
|
||||||
|
(*llist)->tail = trav->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a node that has the value of key
|
||||||
|
// If there are duplicate keys, the first one encountered
|
||||||
|
// will be returned.
|
||||||
|
TNode *find_node(TNode *llist, unsigned int key) {
|
||||||
|
if(llist == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
TNode *trav = llist;
|
||||||
|
|
||||||
|
while(trav != NULL && trav->key != key)
|
||||||
|
trav = trav->next;
|
||||||
|
|
||||||
|
return trav;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge the node provided with either the node after or the node before.
|
||||||
|
// You need to manage merging the data in node->pdata yourself. This code just
|
||||||
|
// deletes the larger of the two nodes.
|
||||||
|
// dir = 0: Merge with node before
|
||||||
|
// dir = 1: Merge with node after
|
||||||
|
|
||||||
|
void merge_node(TNode *llist, TNode *node, int dir) {
|
||||||
|
if(dir == 0) {
|
||||||
|
if(node->prev == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete_node(&llist, node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(dir == 1) {
|
||||||
|
if(node->next == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete_node(&llist, node->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go over every element of llist, and call func
|
||||||
|
// func prototype is void func(TNode *);
|
||||||
|
|
||||||
|
void process_list(TNode *llist, void (*func)(TNode *)) {
|
||||||
|
TNode *trav = llist;
|
||||||
|
while(trav) {
|
||||||
|
func(trav);
|
||||||
|
trav = trav->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Purge the entire list. You must
|
||||||
|
// free any dynamic data in the TData
|
||||||
|
// struct yourself.
|
||||||
|
void purge_list(TNode **llist) {
|
||||||
|
TNode *trav = *llist, *tmp;
|
||||||
|
while(trav) {
|
||||||
|
tmp = trav->next;
|
||||||
|
free(trav);
|
||||||
|
trav = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
*llist = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reset traverser
|
||||||
|
// where=0 START: Resets traverser to start of list
|
||||||
|
// where=1 END: Rsets
|
||||||
|
void reset_traverser(TNode *llist, int where)
|
||||||
|
{
|
||||||
|
if(llist == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(where == FRONT)
|
||||||
|
llist->trav = llist;
|
||||||
|
else
|
||||||
|
if(where == REAR)
|
||||||
|
llist->trav = llist->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next node
|
||||||
|
TNode *succ(TNode *llist)
|
||||||
|
{
|
||||||
|
if(llist == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
TNode *ret = llist->trav;
|
||||||
|
|
||||||
|
if(llist->trav != NULL)
|
||||||
|
llist->trav = llist->trav->next;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the previous node
|
||||||
|
TNode *pred(TNode *llist)
|
||||||
|
{
|
||||||
|
if(llist == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
TNode *ret = llist->trav;
|
||||||
|
|
||||||
|
if(llist->trav != NULL)
|
||||||
|
llist->trav = llist->trav->prev;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
115
labs/cs2106/labs/lab4/linkedlist/wf/llist.h
Normal file
115
labs/cs2106/labs/lab4/linkedlist/wf/llist.h
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// Uncomment the next line to enable debug printing
|
||||||
|
#define DEBUG // Enable debug printing
|
||||||
|
|
||||||
|
// The debug printer; used like a normal printf, except
|
||||||
|
// that printing can be turned off by commenting out the
|
||||||
|
// #define DEBUG above.
|
||||||
|
void dbprintf(char *format, ...);
|
||||||
|
|
||||||
|
// You should modify this structure to hold
|
||||||
|
// whatever you need to implement your
|
||||||
|
// memory manager. You can delete the
|
||||||
|
// val field. It is only used for testlist.c
|
||||||
|
|
||||||
|
typedef struct td {
|
||||||
|
bool occupied;
|
||||||
|
size_t size;
|
||||||
|
} TData;
|
||||||
|
|
||||||
|
/* -----------------------------------------
|
||||||
|
BASIC ROUTINES
|
||||||
|
|
||||||
|
Basic linked list routines
|
||||||
|
|
||||||
|
---------------------------------------- */
|
||||||
|
|
||||||
|
// Basic double linked list node.
|
||||||
|
|
||||||
|
typedef struct tn {
|
||||||
|
unsigned int key;
|
||||||
|
TData *pdata; // Pointer to the data you want to store
|
||||||
|
|
||||||
|
struct tn *trav; // Only used in the root for traversal
|
||||||
|
struct tn *tail; // Only used in the root for finding the end of the list
|
||||||
|
struct tn *prev;
|
||||||
|
struct tn *next;
|
||||||
|
} TNode;
|
||||||
|
|
||||||
|
// Insert Direction
|
||||||
|
#define ASCENDING 0
|
||||||
|
#define DESCENDING 1
|
||||||
|
|
||||||
|
// Merge direction
|
||||||
|
#define PRECEDING 0
|
||||||
|
#define SUCCEEDING 1
|
||||||
|
|
||||||
|
// Traverser position
|
||||||
|
#define FRONT 0
|
||||||
|
#define REAR 1
|
||||||
|
|
||||||
|
// Create a new node. You need to
|
||||||
|
// Create your own TData node, populate
|
||||||
|
// it, then create a new node with a suitable
|
||||||
|
// key. Insertion into the link list is
|
||||||
|
// by ascending order of the key. An example key
|
||||||
|
// might be the starting address of a memory segment.
|
||||||
|
|
||||||
|
TNode *make_node(unsigned int key, TData *data);
|
||||||
|
|
||||||
|
// Inserts a node into the correct point of the
|
||||||
|
// double linked list. The list is sorted
|
||||||
|
// in ascending order of the key. Duplicate keys
|
||||||
|
// are permitted, though not recommended.
|
||||||
|
// llist = Pointer to link list
|
||||||
|
// node = Pointer to node created by make_node
|
||||||
|
// dir = 0: Insert in ascending order
|
||||||
|
// dir = 1: Insert in descending order
|
||||||
|
|
||||||
|
void insert_node(TNode **llist, TNode *node, int dir);
|
||||||
|
|
||||||
|
// Remove a given node from the linked list
|
||||||
|
void delete_node(TNode **llist, TNode *node);
|
||||||
|
|
||||||
|
// Find a node that has the value of key
|
||||||
|
// If there are duplicate keys, the first one encountered
|
||||||
|
// will be returned.
|
||||||
|
TNode *find_node(TNode *llist, unsigned int key);
|
||||||
|
|
||||||
|
// Merge the node provided with either the node after or the node before.
|
||||||
|
// You need to manage merging the data in node->pdata yourself. This code just
|
||||||
|
// deletes the larger of the two nodes.
|
||||||
|
// dir = 0: Merge with node before
|
||||||
|
// dir = 1: Merge with node after
|
||||||
|
|
||||||
|
void merge_node(TNode *llist, TNode *node, int dir);
|
||||||
|
|
||||||
|
// Purge the entire list. You must
|
||||||
|
// free any dynamic data in the TData
|
||||||
|
// struct yourself.
|
||||||
|
void purge_list(TNode **llist);
|
||||||
|
|
||||||
|
/* -----------------------------------------
|
||||||
|
TRAVERSAL ROUTINES
|
||||||
|
|
||||||
|
Lets you traverse the linked list
|
||||||
|
|
||||||
|
---------------------------------------- */
|
||||||
|
|
||||||
|
// Go over every element of llist, and call func
|
||||||
|
// func prototype is void func(TNode *);
|
||||||
|
|
||||||
|
void process_list(TNode *llist, void (*func)(TNode *));
|
||||||
|
|
||||||
|
// Reset traverser
|
||||||
|
// where=0 START: Resets traverser to start of list
|
||||||
|
// where=1 END: Rsets
|
||||||
|
void reset_traverser(TNode *llist, int where);
|
||||||
|
|
||||||
|
// Get the next node
|
||||||
|
TNode *succ(TNode *llist);
|
||||||
|
|
||||||
|
// Get the previous node
|
||||||
|
TNode *pred(TNode *llist);
|
||||||
103
labs/cs2106/labs/lab4/linkedlist/wf/mymalloc.c
Normal file
103
labs/cs2106/labs/lab4/linkedlist/wf/mymalloc.c
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#include "mymalloc.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/_types/_null.h>
|
||||||
|
|
||||||
|
#include "llist.h"
|
||||||
|
|
||||||
|
char _heap[MEMSIZE] = {0};
|
||||||
|
TNode *_memlist = NULL; // To maintain information about length
|
||||||
|
|
||||||
|
// Do not change this. Used by the test harness.
|
||||||
|
// You may however use this function in your code if necessary.
|
||||||
|
long get_index(void *ptr) {
|
||||||
|
if (ptr == NULL)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return (long)((char *)ptr - &_heap[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocates size bytes of memory and returns a pointer
|
||||||
|
// to the first byte.
|
||||||
|
void *mymalloc(size_t size) {
|
||||||
|
if (_memlist == NULL) {
|
||||||
|
TData *data = malloc(sizeof(TData));
|
||||||
|
data->occupied = false;
|
||||||
|
data->size = MEMSIZE;
|
||||||
|
_memlist = make_node(0, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop through the list to find a free block
|
||||||
|
// if found, split the block and return the pointer
|
||||||
|
// if not found, return NULL
|
||||||
|
TNode *curr = _memlist;
|
||||||
|
TNode *best = NULL;
|
||||||
|
while (curr != NULL) {
|
||||||
|
if (curr->pdata->occupied == true) {
|
||||||
|
curr = curr->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (curr->pdata->size < size) {
|
||||||
|
curr = curr->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (best == NULL) {
|
||||||
|
best = curr;
|
||||||
|
curr = curr->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (best->pdata->size < curr->pdata->size) {
|
||||||
|
best = curr;
|
||||||
|
curr = curr->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
if (best == NULL)
|
||||||
|
return NULL;
|
||||||
|
best->pdata->occupied = true;
|
||||||
|
if (best->pdata->size > size) {
|
||||||
|
// Create a new node with the leftover space
|
||||||
|
TData *newData = malloc(sizeof(TData));
|
||||||
|
newData->occupied = false;
|
||||||
|
newData->size = best->pdata->size - size;
|
||||||
|
TNode *newNode = make_node(best->key + size, newData);
|
||||||
|
// insert new node after the current one in the list.
|
||||||
|
insert_node(&_memlist, newNode, 0);
|
||||||
|
// change the size of the current node.
|
||||||
|
best->pdata->size = size;
|
||||||
|
}
|
||||||
|
return &_heap[best->key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees memory pointer to by ptr.
|
||||||
|
void myfree(void *ptr) {
|
||||||
|
if (ptr == NULL)
|
||||||
|
return;
|
||||||
|
long index = get_index(ptr);
|
||||||
|
TNode *node = find_node(_memlist, index);
|
||||||
|
if (node == NULL)
|
||||||
|
return;
|
||||||
|
node->pdata->occupied = false;
|
||||||
|
// merge with the next node if it is free
|
||||||
|
while (node->next != NULL && node->next->pdata->occupied == false) {
|
||||||
|
node->pdata->size += node->next->pdata->size;
|
||||||
|
merge_node(_memlist, node, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (node->prev != NULL && node->prev->pdata->occupied == false) {
|
||||||
|
TNode *prev = node->prev;
|
||||||
|
prev->pdata->size += node->pdata->size;
|
||||||
|
merge_node(_memlist, node, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_node(TNode *node) {
|
||||||
|
printf("Status: %s Start index: %d Length: %zu\n",
|
||||||
|
node->pdata->occupied ? "ALLOCATED" : "FREE", node->key,
|
||||||
|
node->pdata->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_memlist() { process_list(_memlist, print_node); }
|
||||||
7
labs/cs2106/labs/lab4/linkedlist/wf/mymalloc.h
Normal file
7
labs/cs2106/labs/lab4/linkedlist/wf/mymalloc.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#define MEMSIZE 64 * 1024 // Size of memory in bytes
|
||||||
|
|
||||||
|
long get_index(void *ptr);
|
||||||
|
void print_memlist();
|
||||||
|
void *mymalloc(size_t);
|
||||||
|
void myfree(void *);
|
||||||
36
labs/cs2106/labs/lab4/linkedlist/wf/testmalloc.c
Normal file
36
labs/cs2106/labs/lab4/linkedlist/wf/testmalloc.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "mymalloc.h"
|
||||||
|
|
||||||
|
void testalloc(long size, char *ptrname, char **ptr) {
|
||||||
|
printf("\nAllocating %ld bytes to %s\n", size, ptrname);
|
||||||
|
*ptr = mymalloc(size);
|
||||||
|
|
||||||
|
if(*ptr == NULL)
|
||||||
|
printf("Allocation failed.\n");
|
||||||
|
print_memlist();
|
||||||
|
}
|
||||||
|
|
||||||
|
void testfree(char *ptr, char *ptrname) {
|
||||||
|
printf("\nFreeing %s\n", ptrname);
|
||||||
|
myfree(ptr);
|
||||||
|
print_memlist();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
|
||||||
|
|
||||||
|
testalloc(2048, "ptr1", &ptr1);
|
||||||
|
testalloc(6144, "ptr2", &ptr2);
|
||||||
|
testalloc(1024, "ptr3", &ptr3);
|
||||||
|
testfree(ptr2, "ptr2");
|
||||||
|
testalloc(2048, "ptr2", &ptr2);
|
||||||
|
testalloc(4096, "ptr4", &ptr4);
|
||||||
|
testfree(ptr2, "ptr2");
|
||||||
|
testalloc(3072, "ptr5", &ptr5);
|
||||||
|
testfree(ptr1, "ptr1");
|
||||||
|
testfree(ptr2, "ptr2");
|
||||||
|
testfree(ptr3, "ptr3");
|
||||||
|
testfree(ptr4, "ptr4");
|
||||||
|
testfree(ptr5, "ptr5");
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user