2

我必须动态分配一个连续的存储块来保存任意数据类型的二维数组。
它只能使用一次调用malloc.
部分内存必须包含“指向数据类型的指针”和数据类型本身的混合数据类型。
任意数据类型称为Type. 完全披露:是的,这是一个任务。30 多个小时以来,我一直在努力解决这个问题。我不能使用 C99+ 标准。它必须是 C99 之前的版本。

我到目前为止有这个:

Type **Create2D(size_t rows, size_t cols) {
    Type **ptr = (Type **)SafeMalloc(rows * sizeof(Type*) + rows * cols * sizeof(Type)); 
    //  rows*sizeof(Type*) is total memory needed for the elements to store the pointers. 
    //  rows*cols*sizeof(Type) is the memory needed to store the actual array data
    //  The sum of the above two gives the total amount of contiguous memory needed

    int index;
    for (index = 0; index < (int)rows; index++)
        ptr[index] = &ptr + rows*sizeof(Type *) + index * cols * sizeof(Type);
        //  in my mind, this assigns the pointers to the address of each column
        //  to the first address blocks allocated by malloc
}

Type数据类型由提供的头文件定义,使用如下typedef

#define ELEMENTS 9
typedef signed char Type[ELEMENTS];
#undef ELEMENTS

SafeMalloc 函数仅包含错误检查以及 malloc 调用

static Type **SafeMalloc(size_t size) {
    void *vp;       
    if ((vp = malloc(size)) == NULL) {
        fputs("Out of memory\n", stderr);
        exit(EXIT_FAILURE);
    }
    return(vp);
}

我的 Create2D 函数从 main 调用如下,其中rowscols设置为由 for 循环提供的不同值,以便它们通过此处列出的代码更改每次运行:

Type **ppobj;
int rows, cols;
ppobj = Create2D((size_t)rows, (size_t)cols);

该数组在此处的另一个循环中被调用和测试:

int x = Test2D(ppObj, rows, cols);

定义为:

int Test2D(Type **ppObj, int dim0, int dim1) {
    signed char testValue;
    int row, col, ix;       
    Type item;

    testValue = SCHAR_MIN;  
    for (row = 0; row < dim0; ++row) {
        for (col = 0; col < dim1; ++col) {
            for (ix = 0; ix < (int)(sizeof(item) / sizeof(item[0])); ++ix) {                
                ppObj[row][col][ix] = testValue;
                //  throws an exception in above step while stepping through at col = 1.
                if (testValue == SCHAR_MAX)
                    testValue = SCHAR_MIN;
                else
                   ++testValue;
            }
        }
    }
    ....
}

最后,我认为我所拥有的很接近。给定一个 1x27 数组,它会通过它,但是当我调用释放内存的函数然后调用 2x26 数组时,它会在上述步骤中出错。它进入了 3x25 阵列,并且在上面也犯了错误。我的免费功能如下所示:

void Free2D(void *ptr) {
    free(ptr);
}

从上面的主函数中使用这个语法调用它:

Free2D((void *)ppObj);

我也运行过它,并看到dim1嵌套 for 循环中间的变量从它的设置值从传递的参数变为像 1830342 或某种巨大的东西。这让我相信我free()没有正确使用该功能。

4

1 回答 1

3

您的代码几乎是正确的,计算公式ptr[index]不正确:您必须将字节偏移量从转换中计算ptr为字节指针。

这是一个更好的版本:

Type **Create2D(size_t rows, size_t cols) {
    Type **ptr = (Type **)SafeMalloc(rows * sizeof(Type*) + rows * cols * sizeof(Type)); 
    //  rows*sizeof(Type*) is total memory needed for the elements to store the pointers. 
    //  rows*cols*sizeof(Type) is the memory needed to store the actual array data
    //  The sum of the above two gives the total amount of contiguous memory needed

    size_t index;
    for (index = 0; index < rows; index++) {
        ptr[index] = (Type*)((unsigned char*)ptr + rows * sizeof(Type *) + index * cols * sizeof(Type));
       //  in my mind, this assigns the pointers to the address of each column
       //  to the first address blocks allocated by malloc
    }
    return ptr;
}

仍然存在潜在的对齐问题:Type可能需要比Type*. 考虑到这一点,您可以单独计算索引大小并将数据部分对齐大小的倍数Type

Type **Create2D(size_t rows, size_t cols) {
    size_t index_size = (size_t)((unsigned long long)(rows * sizeof(Type*)) * sizeof(Type) / sizeof(Type));
    Type **ptr = (Type **)SafeMalloc(index_size + rows * cols * sizeof(Type)); 
    //  index_size is total memory needed for the elements to store the pointers. 
    //  rows*cols*sizeof(Type) is the memory needed to store the actual array data
    //  The sum of the above two gives the total amount of contiguous memory needed

    size_t index;
    for (index = 0; index < rows; index++) {
        ptr[index] = (Type*)((unsigned char*)ptr + index_size + index * cols * sizeof(Type));
    }
    return ptr;
}
于 2016-02-13T21:19:39.730 回答