Выровненное распределение памяти - PullRequest
1 голос
/ 03 августа 2010

У меня есть следующее назначение:

Напишите функцию на C, которая выделяет блок памяти и возвращает указатель на начало памяти при следующих условиях:

  1. Все адреса в блоке делятся на 32
  2. Выделено по крайней мере необходимое количество байтов
  3. Каждая ячейка в блоке инициализируется нулем
  4. Без глобальных вариантов, минимальная сложность

Напишите другую функцию, которая также освобождает выделенную вами память. (Вы знаете, что вышеупомянутая память была выделена первой функцией, которую вы только что написали).

Вот временное решение для отладки:

"aligned_malloc.h":

#ifndef  __ALIGNED_MALLOC_H__
#define  __ALIGNED_MALLOC_H__

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define ALIGNMENT 16

#if ALIGNMENT > 255
#error "This 'void *aligned_malloc(size_t size)' function can only handle alignment < 256"
#endif

#if ALIGNMENT < 0
#error "This 'void *aligned_malloc(size_t size)' function can only handle a non negative alignment"
#endif

void* aligned_malloc(size_t size);
void aligned_free(void *aligned_p);

#endif /* __ALIGNED_MALLOC_H__ */

"alligned_malloc.c":

#include "aligned_malloc.h"

#undef  DEBUG
#define DEBUG 1

int main()
{
    size_t size = 0;
    void *memblk = NULL;

    do while (size > 0 )
    {
        printf("\nPlease enter in bytes the memory block size you want to allocate (0 to exit): ");
        scanf("%d", &size);
        memblk = aligned_malloc(size);

        #ifdef     DEBUG
            printf("%s[%d]: memblk = 0x%x\n", __FUNCTION__, __LINE__, memblk);
        #endif  /* DEBUG */

    }

    if (memblk != NULL)
        aligned_free(memblk);

    return 0;
}

void *aligned_malloc(size_t size)
{
    int i = 0;
    void* memblk = malloc(size + ALIGNMENT);
    printf ("\n%ld",(long)memblk);

    //offset is the start address of memblk (long=8digit) modulo the ALIGNMENT
    unsigned char offset = ALIGNMENT - ((long)memblk % ALIGNMENT);
    printf ("\n%d",offset);

    if (memblk == NULL)
        return NULL;
    /* O/W: */  
    #ifdef     DEBUG
    printf("%s[%d]: memblk = 0x%x\n", __FUNCTION__, __LINE__, memblk);
    #endif  /* DEBUG */
    for (i = offset; i < size + ALIGNMENT; i++) 
    {
        printf("%02d: %08d\n", i, memblk+i);
        memblk[i] = 0;
    }

    *(memblk + offset - 1) = offset;

    return (void*)(memblk + offset);
}

void aligned_free(void *aligned_p)
{
    unsigned char offset = (unsigned char)(*((unsigned char *)aligned_p-1));
    #ifdef     DEBUG
    printf("%s[%d]: offset = %d\n", __FUNCTION__, __LINE__, offset);
    printf("%s[%d]: aligned_p-1 = 0x%x\n", __FUNCTION__, __LINE__, (unsigned char *)aligned_p-1);
    printf("%s[%d]: aligned_p-offset = 0x%x\n", __FUNCTION__, __LINE__, aligned_p-offset);
    #endif  /* DEBUG */
    free(aligned_p-offset);
}

Теперь у меня есть несколько проблем:

  1. В main()
  2. Я не могу понять, как использовать calloc вместо malloc
  3. Если я использую void*, есть ли возможность преобразовать его в 32-байтовые куски?

Ответы [ 3 ]

2 голосов
/ 03 августа 2010

Ваш код работает правильно: вы определяете, сколько байтов пропустить до выровненного блока, и записываете число в байте до начала блока.У вас есть пара основных проблем:

В C у вас есть либо цикл do { ... } while(cond), либо цикл while(cond) { ... }, но вы их перепутали.Ваш синтаксис do while недопустим, похоже, что вы просто хотите цикл while.

Вы не можете делать арифметику указателей для указателя void *, потому что void не имеет размера.Вычислите ваш новый адрес как long: ((long)memblk+offset) или как указатель на тип, размер которого составляет один байт (например, символ).На данный момент добавление относится к типу void *, что приводит к вашей другой ошибке компиляции.

Догадаться, какие ошибки компиляции вы видите в коде, довольно сложно - в будущем будет проще, если вы опубликуете ошибки,смотри также.

0 голосов
/ 04 августа 2010

Моя ошибка SoRRy: - |

Только обратные адреса должны делиться на 32, т. Е. 100B -> 64 ... 164. ALIGNMENT должен быть установлен равным 32 в заголовочном файле, и вот рабочий код:

#include "aligned_malloc.h"

#undef  DEBUG
#define DEBUG 1

int main(void)
{
  size_t size = 0;
  void *res = NULL;

  printf("\nPlease enter size: ");
  scanf("%d", &size);

  while (size > 0) {

    res = aligned_malloc(size);

#ifdef     DEBUG
    printf("%s[%d]: res = 0x%x\n", __FUNCTION__, __LINE__, res);
#endif  /* DEBUG */

    if (res != NULL)
      aligned_free(res);

    printf("\nPlease enter size again (enter 0 to quit): ");
    scanf("%d", &size);
  }

  return 0;
}

void *aligned_malloc(size_t size)
{
  int i = 0;
  long *res = malloc(size + ALIGNMENT);
  unsigned char offset = ALIGNMENT - ((long)res % ALIGNMENT);

  if (res == NULL)
    return NULL;
  /* O/W: */  
#ifdef     DEBUG
  printf("%s[%d]: res = 0x%x\n", __FUNCTION__, __LINE__, res);
#endif  /* DEBUG */
  for (i = offset; i < size + ALIGNMENT; i++) {
      printf("%02d: %08d\n", i, res+i);
      res[i] = 0;
  }

  *(res + offset - 1) = offset;

  return (void*)(res + offset + 1);
}

void aligned_free(void *aligned_p)
{
  unsigned char offset = (unsigned char)(*((unsigned char *)aligned_p-1));
#ifdef     DEBUG
  printf("%s[%d]: offset = %d\n", __FUNCTION__, __LINE__, offset);
  printf("%s[%d]: aligned_p-1 = 0x%x\n", __FUNCTION__, __LINE__, (unsigned char *)aligned_p-1);
  printf("%s[%d]: aligned_p-offset = 0x%x\n", __FUNCTION__, __LINE__, aligned_p-offset);
#endif  /* DEBUG */
  free(aligned_p-offset);
}

PS Я действительно не знаю, возможно ли получить куски 32B ... THNX

0 голосов
/ 03 августа 2010

Ваш синтаксис do-while неправильный.Должно быть:

do
{
   /* stuff to do */
} while(xxx);

Относительно calloc требуется (1) количество «вещей», которые вы хотите выделить, и (2) размер каждой вещи.Он возвращает нулевой блок памяти с пробелом для хранения этого количества вещей.

Я не понимаю бит о приведении void * к 32-битным блокам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...