我正在研究一个处理图形的C ++程序。
我将图存储为节点的邻接列表,并且我在.h文件中声明了相应的结构,如下所示:
typedef struct Node {
int val;
struct Node * next;
} node;
typedef struct Graph {
int v;
node ** arr;
node ** arr2; // reserved list for a reversed directed graph.
} graph;
我有一个初始化图形的函数,如下所示:
graph * creategraph(int v) { // v == number of vertices
int i;
graph * temp = (graph*)malloc(sizeof(graph));
temp->v = v;
for(i = 0; i < v; i++) {
temp->arr = (node**)malloc(v*sizeof(node*));
}
for(i = 0; i < v; i++) {
temp->arr[i] = NULL;
}
return temp;
}
我调用如下所示的函数创建一个顶点数等于num_vertices
的图形:
graph * g = creategraph (num_vertices);
num_vertices
等于200000
时,graph * createGraph
首次执行时temp->arr[i] = NULL;
会引发“访问冲突写入位置”异常。
有谁能告诉我这里的问题是什么?谢谢。
答案 0 :(得分:3)
问题在于,您不必要地分配temp->arr
v
次,并泄漏所有以前的分配,因此您可以根据需要使用v
倍的内存。你只需要分配一次,所以摆脱循环。
答案 1 :(得分:3)
这是一个很大的问题:
for(i = 0; i < v; i++) {
temp->arr = (node**)malloc(v*sizeof(node*));
}
这为v
个节点分配空间,但是只有指向最后一个节点的指针。这是内存泄漏。你需要做的是:
temp->arr = (node**)malloc(v*sizeof(*temp->arr));
for(i = 0; i < v; i++) {
temp->arr[v] = (node*)malloc(sizeof(*temp->arr[0]));
}
说明:
arr
是指向Node
指针的指针。首先,我们需要为v
指针分配内存。然后我们需要为这些指针的每个分配Node
的内存。
另请注意,在C中强制转换malloc是不必要的(因而也是不好的)。如果您正在编写C ++,那么就必须这样做,所以如果你编写“C”但是使用的是C ++编译器,你需要转换它结果
旁注:
最好先写int arr = malloc(n*sizeof(*arr))
或int arr = malloc(n*sizeof(arr[0]))
而不是int arr = malloc(n*sizeof(int))
。原因是,如果您将来决定要使用long
而不是int
,则不必在多个地方更改它。