views:

285

answers:

4

I'm writing software to simulate the "first-fit" memory allocation schema.

Basically, I allocate a large X megabyte chunk of memory and subdivide it into blocks when chunks are requested according to the schema.

I'm using a linked list called "node" as a header for each block of memory (so that we can find the next block without tediously looping through every address value.

head_ptr = (char*) malloc(total_size + sizeof(node));

if(head_ptr == NULL) return -1; // Malloc Error .. :-(

node* head_node = new node; // Build block header

head_node->next = NULL;
head_node->previous = NULL;

// Header points to next block (which doesn't exist yet)
memset(head_ptr,head_node, sizeof(node));

`

But this last line returns:

 error: invalid conversion from 'node*' to 'int'

I understand why this is invalid.. but how can I place my node into the pointer location of my newly allocated memory?

+1  A: 

Read the docs. memset takes an int (but interpreted as a unsigned char) as a second parameter. This specifies the value to set the first n bytes, where n is the third parameter, of the memory region to.

You could use memcpy, which will copy one region of memory to another. Try:

memcpy(head_ptr, head_node, sizeof(node));

EDIT: Another alternative is to use a pointer cast of head_ptr to set the previous and next values, as suggested by Simon.

Matthew Flaschen
A: 

You cannot assign pointers like that. Second argument is int to be repeted.

From memset(3):

SYNOPSIS
     #include <string.h>

     void *
     memset(void *b, int c, size_t len);

DESCRIPTION
     The memset() function writes len bytes of value c (converted to
     an unsigned char) to the byte string b.

RETURN VALUES
     The memset() function returns its first argument.
Nikolai N Fetissov
+2  A: 
memset(void* memory, int value, size_t size)

So, it's not to copy the head_node into head_ptr (you are thinking of memcpy), it's for initializing memory (clearing to 0, marking as freed, etc...).

In this case, you could simply cast the head_ptr to a node*:

node* head_node = (node*)head_ptr;

And now you don't have to delete head_node, or copy the values to head_ptr at all.

Simon Buchan
Thank you for this elegant solution. You are correct, I was confusing the purpose of memset with memcpy and I see how that could have also worked.
pws5068
+1  A: 

If I understand your question correctly, you want to construct your node object into the memory allocated and pointed to by head_ptr. If you need the node constructor to be called, you do this via the placement new operator like so:

node* head_node = new(head_ptr) node;

If you do need to make sure that the destructor is called as well, then you have to call delete manually:

head_node->~node();
zdan
If he's using `placement new` then he should also use `placement delete` -- can make no assumptions without the definition of `node`. Chances are `placement new` can be skipped altogether as it's probably just a dumb `struct`.
vladr
Placement new would be `new (head_ptr) node`, you are constructing a `node` with `head_ptr` as an argument.
Simon Buchan
@Simon - whoops, thanks for catching that.
zdan
@Vlad: Nitpicking, but C++ guarantees placement delete is a noop. The inverse of `new (ptr) T` is `ptr->~T()`.
Simon Buchan
@Simon, the reason why I brought it up is that we do not know whether or not his `node` is a dumb struct or not, i.e. whether his destructor actually does anything (for all we know, he could have a `std::string` member in his `node` which has to be destructed.) :)
vladr
@Vlad: Which is why it's important to know that `delete (ptr) T` does nothing. You have to call the destructor manually.
Simon Buchan