Смежный блок памяти с malloc - PullRequest
       17

Смежный блок памяти с malloc

1 голос
/ 12 февраля 2010

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

int **CreateInt2D(size_t rows, size_t cols)
{
    int **p, **p1, **end;
    p = (int **)SafeMalloc(rows * sizeof(int *));
    cols *= sizeof(int);
    for (end = p + rows, p1 = p; p1 < end; ++p1)
        *p1 = (int *)SafeMalloc(cols);
    return(p);
}

void *SafeMalloc(size_t size)
{
    void *vp;

    if ((vp = malloc(size)) == NULL) {
        fputs("Out of mem", stderr);
        exit(EXIT_FAILURE);
    }
    return(vp);
}

Но с одним блоком. Это насколько я получил:

int *Create2D(size_t rows, size_t cols) {
 int **memBlock;
 int **arrayPtr;
 int loopCount;
    memBlock = (int **)malloc(rows * sizeof(int *) + rows * cols * sizeof(int));
    if (arrayPtr == NULL) {
        printf("Failed to allocate space, exiting..."); 
        exit(EXIT_FAILURE);
    }
    for (loopCount = 1; loopCount <= (int)rows; loopCount++) {
        arrayPtr = memBlock + (loopCount * sizeof(int *));
        //I don't think this part is right.  do I need something like arrayPtr[loopCount] = ....
    }
 return(memBlock);
}

Ответы [ 4 ]

1 голос
/ 12 февраля 2010

Похоже, у вас нет четкого представления о том, что именно вы хотите достигать. Документируйте это! Это прояснит ваш разум, и, кроме того, если вы этого не поймете, никто больше этого не сделает, и подобный код - кошмар, который нужно поддерживать (относится даже к вашему, когда время проходит мимо).

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

/*
 * Memory layout example for 2 rows and 3 cols
 *
 *                      1 1 1 1 1 1 1 1 1 1
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |P|P|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|
 * |1|2|1|1|1|2|2|2|3|3|3|1|1|1|2|2|2|3|3|3|
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 * P1 is a pointer coloum data for row 1, points to memory start + offset 2 (assuming sizeof(int) == sizeof(int *))
 * P2 is for row 2, points to memory start + offset 11
 * C1 is coloumn 1 data, etc
 */
int **CreateInt2D(size_t rows, size_t cols)
{
        int **memory_start, **p1, *col_data;
        size_t total_memory_to_allocate;

        total_memory_to_allocate = rows * sizeof(int *) + rows * cols * sizeof(int);
        memory_start = (int **) SafeMalloc(total_memory_to_allocate);

        for (col_data = (int *)(memory_start + rows), p1 = memory_start;
             p1 < (int **)col_data;
             ++p1, col_data += cols * sizeof(int))
                *p1 = col_data;

        return memory_start;
}

Этот пример основан на том, чтобы максимально приблизиться к вашему оригиналу. Ответ Джона Кнеллера с использованием подписки на массив, вероятно, является лучшим способом сделать это.

1 голос
/ 12 февраля 2010

как то так

 int **Create2D(size_t rows, size_t cols) 
 {
    size_t cb = (rows * sizeof(int *)) + (rows * cols * sizeof(int));
    int * pmem = (int *)SafeMalloc(cb);

    int ** prows = (int **)pmem; 
    int * pcol = (int *)&prows[rows]; // point pcol after the last row pointer

    for (int ii = 0; ii < rows; ++ii)
    {
       prows[ii] = pcol;
       pcol += cols;
    }

    return prows;
}
0 голосов
/ 12 февраля 2010

, если вы хотите 2D массив с одним выделением, вы можете использовать calloc :

int** p2DArray = (int**)calloc(rows,cols * sizeof(int));

или просто malloc:

int** p2DArray = (int**)malloc(rows * cols * sizeof(int));

это позволяет нормальное индексирование:

int nCellValue = p2DArray[row][col];
int* pCell = &p2DArray[row][col];
0 голосов
/ 12 февраля 2010

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

Если вы ищете двумерный массив, который использует один блок памяти, то что не так с:

int* array = (int*)malloc(rows * count * sizeof(int));
int* someCellPtr = &array[y * rows + x];

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