views:

338

answers:

6

So I am trying to create a Memory Management System. In order to do this I have a set amount of space (allocated by malloc) and then I have a function myMalloc which will essentially return a pointer to the space allocated. Since we will then try and free it, we are trying to set a header of the allocated space to be the size of the allocated space, using memset.

memset(memPtr,sizeBytes,sizeof(int));

We then need to be able to read this so we can see the size of it. We are attempting to do this by using memcpy and getting the first sizeof(int) bytes into a variable. For testing purposes we are just trying to do memset and then immediately get the size back. I've included the entire method below so that you can see all declarations. Any help would be greatly appreciated! Thanks!

void* FirstFit::memMalloc(int sizeBytes){

node* listPtr = freelist;
void* memPtr;   

// Cycle through each node in freelist
while(listPtr != NULL)
{

    if(listPtr->size >= sizeBytes) 
    {
        // We found our space
        // This is where the new memory allocation begins
        memPtr = listPtr->head;
        memset(memPtr,sizeBytes,sizeof(int));

        void *size;
        memcpy(size, memPtr, sizeof(int));
        // Now let's shrink freelist
        listPtr->size = listPtr->size - sizeBytes;

        int *temp = (int*)listPtr->head + (sizeBytes*sizeof(int));  
        listPtr->head = (int*) temp;
        return memPtr;
    }

    listPtr = listPtr->next;
}

::Edit:: Sorry! When running this, we keep getting a seg fault when attempting to run the memcpy line. We have been playing with different ideas for the past hour or so and honestly just have no idea where the error is occurring.

::Edit2:: I also posted this as a comment, but figured I'd put it here as well, so it was easier to find...

Our problem is that we have an allocated space that we are allowed to work with, specified by one malloc call for 128MB. We can only use this, so we can't initialize size to anything using malloc. I guess, is there a way to do this without initializing size. If not, is there anyway to get the int that the header is set to without using memcpy.

+1  A: 

void *size; is an uninitialized pointer, when you try to memcpy into it, your process will try to write this invalid location resulting seg fault.

Naveen
+3  A: 

The prototype for memcpy is

void * memcpy ( void * destination, const void * source, size_t num );

The problem lies here:

void *size; /* you haven't initialized this variable, and then you're writing to what it points to*/
memcpy(size, memPtr, sizeof(memPtr)); /* because size points to uninitialized memory it seg faults*/

EDIT1: Please review this tutorial on pointers in C and C++ Unless you understand pointers you will not understand why those two lines of code, back to back, are a bad pair.

Jason D
Our problem is that we have an allocated space that we are allowed to work with, specified by one malloc call for 128MB. We can only use this, so we can't initialize size to anything using malloc. I guess, is there a way to do this without initializing size. If not, is there anyway to get the int that the header is set to without using memcpy.
Shiev
@user306557: I believe the memcpy is totally unnecessary there. You found a memory block large enough for the requested size, so just return the starting address of that block. WHy do you want to do memcpy here? Also, as a sidenote, parameters you are passing for `memset` are wrong.
Naveen
What should the parameters for memset be? Because we are currently trying to just do:memset(memPtr, sizeBytes, sizeof(int); int size = *memPtr; However, this is not returning the right size, so what should the parameters be? Thanks!
Shiev
@user306557: http://www.cplusplus.com/reference/clibrary/cstring/memset/
Naveen
Isn't that what we did? We were looking at that while writing it. memPtr is a void*, sizeBytes is an int and sizeof(int) is the number of bytes we want to set to the int in sizeBytes.
Shiev
If you have a buffer you can put it in, you can just put size there and work with it. Like if you did `char *buffer = malloc(SOME_AMOUNT);`, you can put size in the buffer by just doing `size = buffer + any_int;` then work with it like normal.
Brendan Long
Correct me if I'm wrong, I might just not be understanding you, but what with what you put. It looks like size would hold a pointer to the end of the allocated block. The problem with this is, we could not later get the size of the block, since the scope of size would simply be for this method, and would no longer exist, when our free function was called.
Shiev
+1  A: 

if you are writing it in windows... you can use

IsBadWritePtr

To Verify that the calling process has write access to the specified range of memory. There may be three reason

1>pointers is either garbage or NULL

2>the amount you're trying to copy is too much.

i.e. copying past the end of the block of memory. Potentially "backwards" copy of string-literal would also cause this behaviour

char *s = "Hello";
char   t[10];

   memcpy(s, t, 6);
mihirpmehta
IsBadWritePtr is not necessarily a good thing - http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx
Damien_The_Unbeliever
You're right... I was just suggesting... IsBadWritePtr is good or bad is depending on how and where are you using it...
mihirpmehta
+1  A: 

You code has numerous bugs in it - rather than go through them one-by-one, I'll give you a commented version of what it should look like:

void* FirstFit::memMalloc(size_t sizeBytes)  // size_t is the appropriate type for memory sizes
{
    node* listPtr = freelist;
    void* memPtr;   
    // The actual allocation needs to be bigger, to have space to hold the size itself.
    size_t allocSize = sizeBytes + sizeof allocSize;

    // Test to make sure that allocSize didn't wrap around to zero
    if (allocSize < sizeBytes)
    {
        return NULL;
    }

    // Cycle through each node in freelist
    while(listPtr != NULL)
    {

        if(listPtr->size >= allocSize) 
        {
            // We found our space
            // This is where the new memory allocation begins
            memPtr = listPtr->head;

            // Copy the size to the start of the memory region
            memcpy(memPtr, &allocSize, sizeof allocSize);

            // Increment the pointer to be returned past the size
            char *tempPtr = (char *)memPtr;
            memPtr = (void *)(tempPtr + sizeof allocSize);

            // Shrink the block
            listPtr->size -= allocSize;
            tempPtr = (char *)listPtr->head;
            listPtr->head = (void *)(tempPtr + allocSize);

            // TODO: If the block is now zero-sized, remove it from the linked list

            return memPtr;
        }

    listPtr = listPtr->next;
    }

    /* No space */
    return NULL;
}
caf
Thank you so very much! memcpy to set the size worked great!
Shiev
+1  A: 

Your use of memset is very odd:

memset(memPtr,sizeBytes,sizeof(int));

is equivalent to (assuming a 32 bit integer):

*((char *)memPtr + 0) = (sizeByte & 0xFF);
*((char *)memPtr + 1) = (sizeByte & 0xFF);
*((char *)memPtr + 2) = (sizeByte & 0xFF);
*((char *)memPtr + 3) = (sizeByte & 0xFF);

As you can see, it's setting each byte to the same value which is the lower byte of sizeBytes.

I'm not sure what you are intending to do so I can't offer a fix.

R Samuel Klatchko
A: 

In creating your own memory management system, now that you have learned what memset() does and doesn't, hopefully already knowing enough of the low level stuff that you know the difference between memcpy() and memmove(), your next step is to learn about "alignment" and about the guarantees that malloc() fulfills, but your code doesn't.

Secure