Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何修复';从0x4000000000000000读取内存失败(读取4个字节中的0个)';C中的错误_C_Malloc - Fatal编程技术网

如何修复';从0x4000000000000000读取内存失败(读取4个字节中的0个)';C中的错误

如何修复';从0x4000000000000000读取内存失败(读取4个字节中的0个)';C中的错误,c,malloc,C,Malloc,我在C上有一个简单的练习要做。但是当我用malloc初始化变量图时,它不能正确执行操作。这是我的密码: #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef int Weight; typedef struct aux { int vDest; Weight weight; struct aux * next; } TypeEdge; typedef

我在C上有一个简单的练习要做。但是当我用malloc初始化变量图时,它不能正确执行操作。这是我的密码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int Weight;

typedef struct aux {
    int vDest;
    Weight weight;
    struct aux * next;
} TypeEdge;

typedef TypeEdge* TypePointer;

typedef struct {
    TypePointer * listAdj;
    int numVertices;
    int numEdges;
} TypeGraph;

typedef int* TipoInt;

bool initializeGraph(TypeGraph *graph, int nv) {
    if (nv < 0) {
        return false;
    }

    graph->numVertices = nv;
    graph->numEdges = 0;
    int i;
    for (i = 0; i < nv; i++) {
        graph->listAdj = (TypePointer*) malloc(sizeof(TypePointer));
    }
    for (i = 0; i < nv; i++) {
        graph->listAdj[i] = NULL;
    }
    return true;
}

void insertEdge(int v1, int v2, Weight weight, TypeGraph *graph) {
    if (v1 < 0 || v1 > graph->numVertices || v2 < 0 || v2 > graph->numVertices) {
        return;
    }
    TypePointer actual = graph->listAdj[v1];
    while (actual->next) {
        actual = actual->next;
    }
    TypePointer pNew = (TypePointer) malloc(sizeof(TypeEdge));
    pNew->vDest = v2;
    pNew->weight = weight;
    pNew->next = NULL;
    actual->next = pNew;
}

int main() {
    TypeGraph graph;
    bool result = initializeGraph(&graph, 100);
    if (result) {
        insertEdge(2, 3, 1, &graph);
    }
    return 0;
}
#包括
#包括
#包括
输入重量;
类型定义结构辅助{
int vDest;
重量;
结构辅助*下一步;
}字体边缘;
typedef TypeEdge*类型指针;
类型定义结构{
TypePointer*listaj;
智力;
国际努梅德斯;
}打字机;
typedef int*TipoInt;
布尔初始化图(类型图*图形,内部nv){
如果(nv<0){
返回false;
}
图形->数值=nv;
图形->numEdges=0;
int i;
对于(i=0;ilistAdj=(类型指针*)malloc(sizeof(类型指针));
}
对于(i=0;ilistAdj[i]=NULL;
}
返回true;
}
void insertEdge(int v1、int v2、权重、类型图*图形){
如果(v1<0 | | v1>图形->数值垂直度| | v2<0 | | v2>图形->数值垂直度){
返回;
}
类型指针实际值=图形->列表调整[v1];
while(实际->下一步){
实际=实际->下一步;
}
TypePointer pNew=(TypePointer)malloc(sizeof(TypeEdge));
pNew->vDest=v2;
pNew->weight=重量;
pNew->next=NULL;
实际->下一步=pNew;
}
int main(){
类型图;
bool结果=初始化图形(&graph,100);
如果(结果){
插入边缘(2、3、1和图形);
}
返回0;
}
问题是,它没有初始化大小为100 TypePointer的图形,而是只初始化大小为2的图形,并且不执行任何操作。当我尝试在
Clion
上调试它时,它会显示以下错误消息:
从0x4000000000000000读取内存失败(读取4个字节中的0个)
。如果我只是运行代码,它将返回代码11


拜托,有人能帮帮我吗?

你的手上真是一团糟。这是由指针的
typedef
”造成的,但主要是因为您没有分配
nv
指针,而是分配了相同的
listaj
指针,然后立即用
NULL
覆盖指针,造成100个内存泄漏

想想看:

    for (i = 0; i < nv; i++) {
        graph->listAdj = (TypePointer*) malloc(sizeof(TypePointer));
    }
您只尝试分配一个
graph->listAdj
(虽然分配了100次),而不是您想要的
nv
指针。必须立即为
nv
指针分配存储

现在,让我们从头开始,通过删除所有
typedef
s,并简单地为
bool
使用
int
,来清理问题,例如

#include <stdio.h>
#include <stdlib.h>

typedef struct aux {
    int vDest;
    int weight;
    struct aux *next;
} TypeEdge;

typedef struct {
    TypeEdge **listAdj;
    int numVertices;
    int numEdges;
} TypeGraph;
接下来,当您
insertEdge()
时,必须处理插入该顶点的第一条边的情况,或者是否需要迭代到列表的末尾并在那里插入。您还需要调整迭代到结尾的方式,以确保在
actual
NULL
时,不会尝试访问
actual->next
。把这些放在一起,你可以做到:

TypeEdge *insertEdge (int v1, int v2, int weight, TypeGraph *graph) 
{
    if (v1 < 0 || v1 > graph->numVertices || 
        v2 < 0 || v2 > graph->numVertices) {
        return NULL;
    }

    TypeEdge *actual = graph->listAdj[v1];
    while (actual && actual->next)
        actual = actual->next;

    TypeEdge *pNew = malloc(sizeof *pNew);
    if (!pNew) {
        perror ("malloc-pNew");
        return NULL;
    }

    pNew->vDest = v2;
    pNew->weight = weight;
    pNew->next = NULL;

    if (!actual)
        graph->listAdj[v1] = pNew;
    else
        actual->next = pNew;

    return (pNew);
}
如果您已经分配了内存,那么还需要能够释放该内存。类似的短函数集可以处理释放每个列表,例如

void freelist (TypeEdge *l)
{
    while (l) {
        TypeEdge *victim = l;
        l = l->next;
        free (victim);
    }
}

void free_graphlists (TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            freelist (g->listAdj[i]);

    free (g->listAdj);
}
总而言之,你可以做到:

#include <stdio.h>
#include <stdlib.h>

typedef struct aux {
    int vDest;
    int weight;
    struct aux *next;
} TypeEdge;

typedef struct {
    TypeEdge **listAdj;
    int numVertices;
    int numEdges;
} TypeGraph;

int initializeGraph (TypeGraph *graph, int nv)
{
    if (nv < 0)
        return 0;

    graph->numVertices = nv;
    graph->numEdges = 0;
    int i;

    if ((graph->listAdj = malloc(sizeof *graph->listAdj * nv)) == NULL) {
        perror ("malloc-graph->listAdj");
        return 0;
    }

    for (i = 0; i < nv; i++)
        (graph->listAdj)[i] = NULL;

    return 1;
}

TypeEdge *insertEdge (int v1, int v2, int weight, TypeGraph *graph) 
{
    if (v1 < 0 || v1 > graph->numVertices || 
        v2 < 0 || v2 > graph->numVertices) {
        return NULL;
    }

    TypeEdge *actual = graph->listAdj[v1];
    while (actual && actual->next)
        actual = actual->next;

    TypeEdge *pNew = malloc(sizeof *pNew);
    if (!pNew) {
        perror ("malloc-pNew");
        return NULL;
    }

    pNew->vDest = v2;
    pNew->weight = weight;
    pNew->next = NULL;

    if (!actual)
        graph->listAdj[v1] = pNew;
    else
        actual->next = pNew;

    return (pNew);
}

void prnedge (const TypeEdge *e)
{
    do
        printf (" %3d %3d\n", e->vDest, e->weight);
    while ((e = e->next));
}

void print_edge (const TypeEdge *e, int edge)
{
    printf ("\nedge %d\n", edge);
    prnedge (e);
}

void print_graph (const TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            print_edge (g->listAdj[i], i);
}

void freelist (TypeEdge *l)
{
    while (l) {
        TypeEdge *victim = l;
        l = l->next;
        free (victim);
    }
}

void free_graphlists (TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            freelist (g->listAdj[i]);

    free (g->listAdj);
}

int main (void) {

    TypeGraph graph;
    int result = initializeGraph (&graph, 100);

    if (result) {
        insertEdge (2, 3, 1, &graph);
        insertEdge (2, 4, 1, &graph);
    }

    print_graph (&graph);
    free_graphlists (&graph);

    return 0;
}
内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于所分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要它时可以释放它

必须使用内存错误检查程序,以确保您不会试图访问内存或写入超出/超出分配的块的边界,尝试在未初始化的值上读取或建立条件跳转,最后确认释放所有已分配的内存

对于Linux,
valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都很容易使用,只需运行程序即可

$ valgrind ./bin/edgetype
==21679== Memcheck, a memory error detector
==21679== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==21679== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==21679== Command: ./bin/edgetype
==21679==

edge 2
   3   1
   4   1
==21679==
==21679== HEAP SUMMARY:
==21679==     in use at exit: 0 bytes in 0 blocks
==21679==   total heap usage: 3 allocs, 3 frees, 832 bytes allocated
==21679==
==21679== All heap blocks were freed -- no leaks are possible
==21679==
==21679== For counts of detected and suppressed errors, rerun with: -v
==21679== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认已释放所有已分配的内存,并且没有内存错误


仔细检查一下,如果您还有其他问题,请告诉我。

您的
初始化图和
插入图中有一些错误。这个改变应该对你有用

bool initializeGraph(TypeGraph *graph, int nv)
{
    if (nv < 0) {
        return false;
    }

    graph->numVertices = nv;
    graph->numEdges = 0;

    /* call `calloc` to avoid using for-loop to zero memory */
    graph->listAdj = calloc(nv, sizeof(TypePointer));

    return true;
}

void insertEdge(int v1, int v2, Weight weight, TypeGraph *graph)
{
    if (v1 < 0 || v1 > graph->numVertices || v2 < 0 || v2 > graph->numVertices) {
        return;
    }

    /* just insert the node at the head of the adjList */
    TypePointer pNew = malloc(sizeof(TypeEdge));

    pNew->vDest = v2;
    pNew->weight = weight;
    pNew->next = graph->listAdj[v1];
    graph->listAdj[v1] = pNew;
    graph->numEdges++;
}
bool初始化图(TypeGraph*graph,int-nv)
{
如果(nv<0){
返回false;
}
图形->数值=nv;
图形->numEdges=0;
/*调用'calloc',以避免使用for循环将内存归零*/
graph->listAdj=calloc(nv,sizeof(TypePointer));
返回true;
}
void insertEdge(int v1、int v2、权重、类型图*图形)
{
如果(v1<0 | | v1>图形->数值垂直度| | v2<0 | | v2>图形->数值垂直度){
返回;
}
/*只需在adjList的开头插入节点*/
TypePointer pNew=malloc(sizeof(TypeEdge));
pNew->vDest=v2;
pNew->weight=重量;
pNew->next=graph->listAdj[v1];
图表->列表调整[v1]=pNew;
图形->numEdges++;
}

至于typedef,请阅读并自行决定是否使用。就我个人而言,除非必要,否则我会避免使用
typedef

避免
typedef
”指针。它隐藏信息。查看:。初始化100次,每次都覆盖上一个指针。
int main (void) {

    TypeGraph graph;
    int result = initializeGraph (&graph, 100);

    if (result) {
        insertEdge (2, 3, 1, &graph);
        insertEdge (2, 4, 1, &graph);
    }

    print_graph (&graph);
    free_graphlists (&graph);

    return 0;
}
#include <stdio.h>
#include <stdlib.h>

typedef struct aux {
    int vDest;
    int weight;
    struct aux *next;
} TypeEdge;

typedef struct {
    TypeEdge **listAdj;
    int numVertices;
    int numEdges;
} TypeGraph;

int initializeGraph (TypeGraph *graph, int nv)
{
    if (nv < 0)
        return 0;

    graph->numVertices = nv;
    graph->numEdges = 0;
    int i;

    if ((graph->listAdj = malloc(sizeof *graph->listAdj * nv)) == NULL) {
        perror ("malloc-graph->listAdj");
        return 0;
    }

    for (i = 0; i < nv; i++)
        (graph->listAdj)[i] = NULL;

    return 1;
}

TypeEdge *insertEdge (int v1, int v2, int weight, TypeGraph *graph) 
{
    if (v1 < 0 || v1 > graph->numVertices || 
        v2 < 0 || v2 > graph->numVertices) {
        return NULL;
    }

    TypeEdge *actual = graph->listAdj[v1];
    while (actual && actual->next)
        actual = actual->next;

    TypeEdge *pNew = malloc(sizeof *pNew);
    if (!pNew) {
        perror ("malloc-pNew");
        return NULL;
    }

    pNew->vDest = v2;
    pNew->weight = weight;
    pNew->next = NULL;

    if (!actual)
        graph->listAdj[v1] = pNew;
    else
        actual->next = pNew;

    return (pNew);
}

void prnedge (const TypeEdge *e)
{
    do
        printf (" %3d %3d\n", e->vDest, e->weight);
    while ((e = e->next));
}

void print_edge (const TypeEdge *e, int edge)
{
    printf ("\nedge %d\n", edge);
    prnedge (e);
}

void print_graph (const TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            print_edge (g->listAdj[i], i);
}

void freelist (TypeEdge *l)
{
    while (l) {
        TypeEdge *victim = l;
        l = l->next;
        free (victim);
    }
}

void free_graphlists (TypeGraph *g)
{
    for (int i = 0; i < g->numVertices; i++)
        if (g->listAdj[i])
            freelist (g->listAdj[i]);

    free (g->listAdj);
}

int main (void) {

    TypeGraph graph;
    int result = initializeGraph (&graph, 100);

    if (result) {
        insertEdge (2, 3, 1, &graph);
        insertEdge (2, 4, 1, &graph);
    }

    print_graph (&graph);
    free_graphlists (&graph);

    return 0;
}
$ ./bin/edgetype

edge 2
   3   1
   4   1
$ valgrind ./bin/edgetype
==21679== Memcheck, a memory error detector
==21679== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==21679== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==21679== Command: ./bin/edgetype
==21679==

edge 2
   3   1
   4   1
==21679==
==21679== HEAP SUMMARY:
==21679==     in use at exit: 0 bytes in 0 blocks
==21679==   total heap usage: 3 allocs, 3 frees, 832 bytes allocated
==21679==
==21679== All heap blocks were freed -- no leaks are possible
==21679==
==21679== For counts of detected and suppressed errors, rerun with: -v
==21679== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
bool initializeGraph(TypeGraph *graph, int nv)
{
    if (nv < 0) {
        return false;
    }

    graph->numVertices = nv;
    graph->numEdges = 0;

    /* call `calloc` to avoid using for-loop to zero memory */
    graph->listAdj = calloc(nv, sizeof(TypePointer));

    return true;
}

void insertEdge(int v1, int v2, Weight weight, TypeGraph *graph)
{
    if (v1 < 0 || v1 > graph->numVertices || v2 < 0 || v2 > graph->numVertices) {
        return;
    }

    /* just insert the node at the head of the adjList */
    TypePointer pNew = malloc(sizeof(TypeEdge));

    pNew->vDest = v2;
    pNew->weight = weight;
    pNew->next = graph->listAdj[v1];
    graph->listAdj[v1] = pNew;
    graph->numEdges++;
}