我正在尝试使用 GCC 编译 64 位 CPP 代码,但是多维(即 2D)数组内存分配一次返回 NULL
我将元素大小从 46,000 增加到 46,500。我的虚拟内存设置为 96GB,硬件使用 32GB Ram 运行 64 位操作系统。 只要 MAX_VERTICES
不超过 46000
,代码就可以正常工作。
以下是我要动态分配的内容:
struct ShortestPath {
real32 totalWeight;
// NOTE: ShortestPath is a list of pointers; does not make copies
// (i.e. side-effects) the pointers point to memory allocated
// in the DijkstraSPTree array in the vehicle_searching module
List<DirectedEdge *> *edgeList;
};
#define MAX_VERTICES 46500
global_variable ShortestPath spAllPairs[MAX_VERTICES][MAX_VERTICES];
在堆上分配内存以替换
spAllPairs[MAX_VERTICES][MAX_VERTICES]
使用以下代码
global_variable ShortestPath **spAllPairs;
global_variable ShortestPath *arr_data;
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
free(spAllPairs); // Function is called multiple times so I clear memory
free(arr_data); // before reallocation given values pointed by pointers
free(spTreesArray); // are used in other files in my project after run.
inline allocate_mem(ShortestPath*** arr, ShortestPath** arr_data, int n, int m);
allocate_mem(&spAllPairs, &arr_data, MAX_VERTICES, MAX_VERTICES);
for (unsigned int k = 0 ; k < MAX_VERTICES ; k++) {
if (spAllPairs[k] == NULL) {
while (k >= 1) {
free(spAllPairs[k]);
--k;
}
free(spAllPairs[0]);
free(spAllPairs);
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
}
spTreesArray = (DijkstraSPTree *)malloc(MAX_VERTICES * sizeof(DijkstraSPTree));
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}
void pathTo(DijkstraSPTree *spTree, ShortestPath *shortestPath, int32 dest)
{
List<DirectedEdge *>::traverseList(freeDirectedEdge, shortestPath->edgeList);
List<DirectedEdge *>::emptyList(&shortestPath->edgeList);
shortestPath->totalWeight = spTree->distTo[dest];
}
int allocate_mem(ShortestPath ***arr, ShortestPath **arr_data, int n, int m)
{
*arr = (ShortestPath **)malloc(n * sizeof(ShortestPath*));
*arr_data = (ShortestPath *)malloc(n * m * sizeof(ShortestPath));
for (int i = 0; i < n; i++)
(*arr)[i] = *arr_data + i * m;
return 0; //free point
}
最佳答案
函数allocate_mem
与getShortestPath
中用于释放结构的代码不一致。如果 arr_data
没有在其他地方使用,您应该删除这个全局变量并以这种方式分配一个间接数组:
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = (ShortestPath **)calloc(n, sizeof(*arr));
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = (ShortestPath *)calloc(m, sizeof(ShortestPath));
if (arr[i] == NULL)
break;
}
}
return arr;
}
注意事项:
- 在
释放
它们指向的内存后,将NULL
存储到全局指针中会更安全。 allocate_mem
检查它是否可以分配所有数组元素并释放分配的所有元素(如果没有)而不是尝试在调用函数中清理会更加一致。
这是一个更一致的版本和调用代码:
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = (ShortestPath **)calloc(n, sizeof(*arr));
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = (ShortestPath *)calloc(m, sizeof(ShortestPath));
if (arr[i] == NULL) {
for (j = i; j-- > 0;) {
free(arr[j]);
}
free(arr);
return NULL;
}
}
}
return arr;
}
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
// Function is called multiple times so I clear memory
// before reallocation given values pointed by pointers
// are used in other files in my project after run.
free(spAllPairs);
spAllPairs = NULL;
free(arr_data);
arr_data = NULL;
free(spTreesArray);
spTreesArray = NULL;
spAllPairs = allocate_mem(MAX_VERTICES, MAX_VERTICES);
if (spAllPairs == NULL) {
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
spTreesArray = (DijkstraSPTree *)malloc(MAX_VERTICES * sizeof(DijkstraSPTree));
if (spTreesArray == NULL) {
fprintf(stderr, "Failed to allocate space for DijkstraSPTree!\n");
exit(1);
}
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}
EDIT 正如 M.M 评论的那样,您应该在 C++ 中使用 new
和 delete
运算符而不是 malloc()
和 free()
。 (或者除了 malloc
之外,但为什么还要费心使用 malloc
):
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = new ShortestPath *[n];
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = new ShortestPath[m];
if (arr[i] == NULL) {
for (j = i; j-- > 0;) {
delete[] arr[j];
}
delete[] arr;
return NULL;
}
}
}
return arr;
}
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
// Function is called multiple times so I clear memory
// before reallocation given values pointed by pointers
// are used in other files in my project after run.
delete[] spAllPairs;
spAllPairs = NULL;
delete[] spTreesArray;
spTreesArray = NULL;
spAllPairs = allocate_mem(MAX_VERTICES, MAX_VERTICES);
if (spAllPairs == NULL) {
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
spTreesArray = new DijkstraSPTree *[MAX_VERTICES];
if (spTreesArray == NULL) {
fprintf(stderr, "Failed to allocate space for DijkstraSPTree!\n");
exit(1);
}
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}
关于c++ - 二维数组内存分配 (malloc) 返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42321273/