Reputation: 223
I'm creating malloc for a project, and allocating space the hard way to understand how it works, but I'm getting null pointer issues.
(given) Block Structure: Linked List
typedef struct block_hd{
/* The blocks are maintained as a linked list */
/* The blocks are ordered in the increasing order of addresses */
struct block_hd* next;
int size_status;
}block_header;
block_header* list_head = NULL;
When I'm adding memory blocks, I'm running into an error with my temp Node. Basically, it's not dereferencing temp_node to get to its next and set it to the proper location. My print out statements:
not empty: 4088
there is space to add
create temp
f7758040
f7754000
00000000
Segmentation fault (core dumped)
It's never getting to temp_node's next. Like it's not creating temp properly. Temp is pointing to headers of blocks. And I'm giving it a location. What is the problem?
My Mem_Alloc function *assume properly initiated linked list:
void* Mem_Alloc(int size)
{
if (size < 1) return NULL;
size = 1 + ((size - 1)/4);
size = size * 4;
if (list_head != NULL){
block_header* head_node = list_head;
while (head_node != NULL){
//get curr header size
int node_size = head_node->size_status;
printf("not empty: %d\n", node_size);
//there is space to add
if (node_size%2 == 0 && (size+sizeof(block_header)) < node_size){
printf("there is space to add\n");
//twocases
if ((node_size - size - sizeof(block_header)) > 0){
printf("create temp\n");
block_header* temp_node = NULL;
temp_node = head_node + sizeof(block_header) + size;
printf("%08x\n", (unsigned int) temp_node);
printf("%08x\n", (unsigned int) head_node);
printf("%08x\n", (unsigned int) head_node->next);
printf("%08x\n", (unsigned int) temp_node->next);
printf("set temp next to head next\n");
temp_node->next = head_node->next;
printf("set temp size to remaining\n");
temp_node->size_status = (head_node->size_status - sizeof(block_header) - size);
printf("set head size to used status\n");
head_node->size_status = size + 1;
printf("set head next to temp\n");
head_node->next = temp_node;
}
else{
//if at end, and not enough space for another header
//keep current size_status - do not reduce current
printf("Not enough space, set head size to used\n");
if (head_node->next != NULL) head_node->size_status = size + 1;
}
//return location of (head_node_location+sizeof(block_header))
return head_node + sizeof(block_header);
}//end if
else{
//headersize%2 equaled 1, so it's used - move on.
printf("STEPPING THROUGH LINKED LIST\n");
head_node = head_node->next;
}
}//end while
}//end if
return NULL;
Upvotes: 0
Views: 323
Reputation: 593
You're getting tripped up by how pointer arithmetic interacts with types.
temp_node = head_node + sizeof(block_header) + size;
I assume that in this line you are trying to advance the pointer size + sizeof(block_header)
bytes. But since the pointers are to block_headers, it is advancing by that byte count times the sizeof(block_header). You could do something like:
/* Advance the pointer then cast */
char *raw_tmp_node = head_node + sizeof(block_header) + size;
block_header *tmp_node = (block_header*)raw_tmp_node;
As an aside, you should read up on the importance of memory alignment. malloc
guarantees that the memory it returns is suitably aligned for any type. Generally, this is done by forcing the alignment with a union, as mentioned in K&R.
union align_storage {
most_strictly_aligned_type x; /* Usually a long; sometimes long long */
char storage[BLOCK_SIZE];
};
Upvotes: 1
Reputation: 229603
temp_node
is set here:
temp_node = head_node + sizeof(block_header) + size;
Incrementing pointers doesn't go by bytes, the addresses are calculated according to the type the pointer points to. So if p
points to element 0 of an array of struct block_struct
, then p+1
will point to the struct block_struct
at index 1 and p+2
will point to the one at index 2.
The initialization of temp_node
seems to assume that head_node
will be incremented by a number of bytes.
You can either change your calculations to work on struct block_struct
s or you can cast your pointers to char*
before doing the pointer arithmetic (char
is one byte).
Upvotes: 2