【问题标题】:Contiguous block of memory with malloc使用 malloc 的连续内存块
【发布时间】:2010-02-12 09:13:25
【问题描述】:

我试图在一个函数调用中创建一个连续的内存块,该函数调用将内存的第一部分作为指向其他块的指针数组。基本上,我正在尝试这样做:

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);
}

【问题讨论】:

    标签: c pointers malloc


    【解决方案1】:

    类似的东西

     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;
    }
    

    【讨论】:

    • 我想我得到了你的答案,但我在为行指针和列分配内存的想法上遇到了麻烦。因此,使用该内存块 cb,您可以只对 pmem 部分进行类型转换以将其分配出去?就像第一部分是指向指针的指针,然后 pcol 指向最后一行指针,然后初始化 cols 并使指向指针 prows 的指针指向 pcol?类似的东西?
    • 是的。您分配总数,然后使用指针数学获取 pcol 指针,该指针指向要分配给 prows 的部分之后的第一个地址,然后遍历 pcol 指针并使用它来初始化 prow 数组。最终结果是一次分配,但布局与原始代码相同。
    • @Crystal:再次检查代码,我在循环中有一个错误。对不起。
    【解决方案2】:

    您似乎并不清楚自己想要什么 实现。 记录下来!它会让你头脑清醒,而且如果你不理解它,其他人也不会, 并且这样的代码是维护的噩梦(甚至适用于您自己的时间 路过)。

    要创建一个分配连续内存块的函数,您只需调用一次 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;
    }
    

    此示例基于尽可能接近您的原始内容,John Knoeller 使用数组订阅的回答可能是一种更好的方法。

    【讨论】:

      【解决方案3】:

      我不太清楚您要做什么,但是您的最后一段代码有问题。您针对 NULL 测试 arrayPtr 但从不分配它。在 for() 循环中,您分配给 arrayPtr 但实际上并没有对它做任何事情。

      如果您正在寻找使用单个内存块的二维数组,那么有什么问题:

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

      ?

      【讨论】:

        【解决方案4】:

        如果你想用一个分配器来做二维数组,你可以使用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];
        

        【讨论】:

          猜你喜欢
          • 2011-01-15
          • 2010-10-12
          • 2019-06-10
          • 2014-02-15
          • 1970-01-01
          • 2023-03-22
          • 2011-05-02
          相关资源
          最近更新 更多