Проблемы с использованием memset и memcpy - PullRequest
2 голосов
/ 01 апреля 2010

Итак, я пытаюсь создать систему управления памятью. Для этого у меня есть установленное количество пространства (выделенное malloc), а затем у меня есть функция myMalloc, которая по существу возвращает указатель на выделенное пространство. Поскольку затем мы попытаемся освободить его, мы пытаемся установить заголовок выделенного пространства равным размеру выделенного пространства, используя memset.

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

Затем нам нужно прочитать это, чтобы увидеть его размер. Мы пытаемся сделать это, используя memcpy и получая первые байты sizeof (int) в переменную. В целях тестирования мы просто пытаемся сделать memset, а затем сразу же получить размер обратно. Я включил весь метод ниже, чтобы вы могли видеть все объявления. Любая помощь будет принята с благодарностью! Спасибо!

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 :: Сожалею! При выполнении этого мы продолжаем получать ошибку сегмента при попытке запустить строку memcpy. Последние несколько часов мы играем с разными идеями и, честно говоря, просто не знаем, где происходит ошибка.

:: Edit2 :: Я также опубликовал это в качестве комментария, но решил, что я тоже разместил его здесь, чтобы его было легче найти ...

Наша проблема в том, что у нас есть выделенное пространство, с которым нам разрешено работать, указанное одним вызовом malloc для 128 МБ. Мы можем использовать только это, поэтому мы не можем инициализировать размер с помощью malloc. Я думаю, есть ли способ сделать это без инициализации размера. Если нет, то есть ли получить int, для которого установлен заголовок, без использования memcpy.

Ответы [ 6 ]

3 голосов
/ 01 апреля 2010

Прототип для memcpy -

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

Проблема заключается здесь:

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: Пожалуйста, просмотрите это руководство по указателям на C и C ++ Если вы не понимаете указатели, вы не поймете, почему эти две строки кода, спина к спине, являются плохой парой.

2 голосов
/ 01 апреля 2010

Использование memset очень странно:

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

эквивалентно (при условии 32-разрядного целого числа):

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

Как видите, он устанавливает каждый байт на одно и то же значение, которое является младшим байтом sizeBytes.

Я не уверен, что вы собираетесь делать, поэтому я не могу предложить исправление.

1 голос
/ 01 апреля 2010

В вашем коде есть множество ошибок - вместо того, чтобы проходить их по одному, я дам вам закомментированную версию того, как это должно выглядеть:

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;
}
1 голос
/ 01 апреля 2010

если вы пишете в Windows ... вы можете использовать

IsBadWritePtr

Чтобы убедиться, что вызывающий процесс имеет доступ на запись в указанный диапазон памяти. Там может быть три причины

1> указатели либо мусор, либо NULL

2> сумма, которую вы пытаетесь скопировать, слишком велика.

т.е. копирование за конец блока памяти. Потенциально «обратная» копия строкового литерала также может вызвать такое поведение

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

   memcpy(s, t, 6);
1 голос
/ 01 апреля 2010

void *size; - неинициализированный указатель, когда вы пытаетесь ввести в него memcpy, ваш процесс попытается записать это неверное местоположение, что приведет к ошибке сегмента.

0 голосов
/ 01 апреля 2010

Создавая собственную систему управления памятью, теперь, когда вы узнали, что делает и что не делает memset (), мы надеемся, что уже достаточно знаем о вещах низкого уровня, что вы знаете разницу между memcpy () и memmove (), вашим Следующий шаг - узнать о «выравнивании» и о гарантиях, которые выполняет malloc (), а ваш код - нет.

...