我必须动态分配一个连续的存储块来保存任意数据类型的2D数组
它只能使用malloc
的一次通话
部分内存必须包含混合数据类型"指向数据类型的指针"和数据类型本身
任意数据类型称为Type
。
完全披露:是的,这是一项任务。我已经在这上面打了30多个小时试图解决这个问题。我不能使用C99 +标准。它必须是Pre-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调用如下,其中rows
和cols
设置为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);
}
使用此sytax调用它,来自上面的主要功能:
Free2D((void *)ppObj);
我也经历了它并看到嵌套for循环中间的dim1
变量从它传递的参数的设置值到1830342或者某些东西的巨大变化分类。这让我相信free()
函数没有被我正确使用。
答案 0 :(得分: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;
}