c - 大小 8 2 的读/写无效

标签 c malloc valgrind sizeof

在我的学校项目上工作时,在 Unix 学校服务器上编译我的项目后,我不断收到来自 Valgrind 的以下错误,并且无法运行该程序,因为我收到“段错误:11”。

==95183== Memcheck, a memory error detector
==95183== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==95183== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==95183== Command: ./Euler
==95183==
==95183== Invalid read of size 8
==95183==    at 0x400B65: GInit (Euler.c:64)
==95183==    by 0x400DD1: main (Euler.c:118)
==95183==  Address 0x1786100 is 0 bytes after a block of size 48 alloc'd
==95183==    at 0x100688B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==95183==    by 0x400A80: GInit (Euler.c:43)
==95183==    by 0x400DD1: main (Euler.c:118)
==95183==
==95183== Invalid write of size 4
==95183==    at 0x400B6B: GInit (Euler.c:64)
==95183==    by 0x400DD1: main (Euler.c:118)
==95183==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==95183==
==95183==
==95183== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==95183==  Access not within mapped region at address 0x0
==95183==    at 0x400B6B: GInit (Euler.c:64)
==95183==    by 0x400DD1: main (Euler.c:118)
==95183==  If you believe this happened as a result of a stack
==95183==  overflow in your program's main thread (unlikely but
==95183==  possible), you can try to increase the size of the
==95183==  main thread stack using the --main-stacksize= flag.
==95183==  The main thread stack size used in this run was 16777216.
==95183==
==95183== HEAP SUMMARY:
==95183==     in use at exit: 32,981 bytes in 16 blocks
==95183==   total heap usage: 16 allocs, 0 frees, 32,981 bytes allocated
==95183==
==95183== LEAK SUMMARY:
==95183==    definitely lost: 0 bytes in 0 blocks
==95183==    indirectly lost: 0 bytes in 0 blocks
==95183==      possibly lost: 0 bytes in 0 blocks
==95183==    still reachable: 32,981 bytes in 16 blocks
==95183==         suppressed: 0 bytes in 0 blocks
==95183== Reachable blocks (those to which a pointer was found) are not shown.
==95183== To see them, rerun with: --leak-check=full --show-reachable=yes
==95183==
==95183== For counts of detected and suppressed errors, rerun with: -v
==95183== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault: 11
eva ~/Algoritmy/Euler> make
gcc -Wall -std=c99 -pedantic -lm -g -o Euler Euler.c
eva ~/Algoritmy/Euler> ./Euler
Segmentation fault: 11 (core dumped [obraz paměti uložen])
eva ~/Algoritmy/Euler>  valgrind --leak-check=yes ./Euler
==96649== Memcheck, a memory error detector
==96649== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==96649== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==96649== Command: ./Euler
==96649==
==96649== Invalid read of size 8
==96649==    at 0x400BF2: GInit (Euler.c:85)
==96649==    by 0x400ECB: main (Euler.c:152)
==96649==  Address 0x1786100 is 0 bytes after a block of size 48 alloc'd
==96649==    at 0x100688B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==96649==    by 0x400A8E: GInit (Euler.c:44)
==96649==    by 0x400ECB: main (Euler.c:152)
==96649==
==96649== Invalid write of size 4
==96649==    at 0x400BF8: GInit (Euler.c:85)
==96649==    by 0x400ECB: main (Euler.c:152)
==96649==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==96649==
==96649==
==96649== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==96649==  Access not within mapped region at address 0x0
==96649==    at 0x400BF8: GInit (Euler.c:85)
==96649==    by 0x400ECB: main (Euler.c:152)
==96649==  If you believe this happened as a result of a stack
==96649==  overflow in your program's main thread (unlikely but
==96649==  possible), you can try to increase the size of the
==96649==  main thread stack using the --main-stacksize= flag.
==96649==  The main thread stack size used in this run was 16777216.
==96649==
==96649== HEAP SUMMARY:
==96649==     in use at exit: 32,981 bytes in 16 blocks
==96649==   total heap usage: 16 allocs, 0 frees, 32,981 bytes allocated
==96649==
==96649== LEAK SUMMARY:
==96649==    definitely lost: 0 bytes in 0 blocks
==96649==    indirectly lost: 0 bytes in 0 blocks
==96649==      possibly lost: 0 bytes in 0 blocks
==96649==    still reachable: 32,981 bytes in 16 blocks
==96649==         suppressed: 0 bytes in 0 blocks
==96649== Reachable blocks (those to which a pointer was found) are not shown.
==96649== To see them, rerun with: --leak-check=full --show-reachable=yes
==96649==
==96649== For counts of detected and suppressed errors, rerun with: -v
==96649== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault: 11

我在使用 malloc 时似乎错误地分配了内存。我知道没有释放内存,因为我还没有实现删除功能。 我为 malloc、fgets 和 fscanf 添加了一些额外的测试,以消除可能的错误。 函数 GInit 应该从文件 Graph1.txt 中读取格式化数据并创建由节点组成的图形。文件包含节点数和关联矩阵。

这是我的代码:

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

#define MAXFILENAME 20

typedef struct tNode{
    int Deg;
    int Val;    
    int* Neigh; 
} *tNodePtr;

typedef struct tGraph{
    int Num;    
    tNodePtr* Nodes;    
} *tGraphPtr;


void GInit(tGraphPtr G, const char *FNum)
{
    char FileName[MAXFILENAME];
    char *FileNamePrefix = "Graph";
    char *FileNamePostfix = ".txt";
    FILE *FilePtr;
    int FileBrowser;
    int i, j, k, countNeigh;
    char *line;
    char c;

    strcpy(FileName, FileNamePrefix);
    strcat(FileName, FNum);
    strcat(FileName, FileNamePostfix);

    FilePtr = fopen(FileName, "r");

    if(!FilePtr)
        printf("Can't open file \"%s\"\n", FileName);
    else
    {
        if(!fscanf(FilePtr, "%d", &FileBrowser))
            printf("fscanf error 1!\n");

        G->Num = FileBrowser;
        G->Nodes = malloc(G->Num * sizeof *(G->Nodes));
        if(G->Nodes == NULL)
        {
            printf("Memory allocation error 1!\n");
            return;
        }

        for(i = 0; i < G->Num; i++)
        {
            G->Nodes[i] = malloc(sizeof *(G->Nodes[i]));
            if(G->Nodes[i] == NULL)
            {
                printf("Memory allocation error 2!\n");
                return;
            }
        }

        line = malloc((2*G->Num + 1) * sizeof *line );
        if(line == NULL)
        {
            printf("Memory allocation error 3!\n");
            return;
        }


        i = 0;
        if(!fscanf(FilePtr, "%c", &c))
            printf("fscanf error 2!\n");
        if(fgets(line, 2*G->Num + 1, FilePtr) == NULL)
            printf("fgets error 1!\n"); 
        while(!feof(FilePtr))
        {
            countNeigh = 0;
            j = 0;
            while(line[j] != '\0')
            {
                if(line[j] == '1')
                    countNeigh++;
                j++;
            }

            G->Nodes[i]->Deg = countNeigh;
            G->Nodes[i]->Val = i;
            G->Nodes[i]->Neigh = malloc(countNeigh * sizeof *(G->Nodes[i]->Neigh));
            if(G->Nodes[i]->Neigh == NULL)
            {
            printf("Memory allocation error 4!\n");
            return;
            }


            j = 0;
            k = 0;
            while(line[j] != '\0')
            {
                if(line[j] == '1')
                {
                    G->Nodes[i]->Neigh[k] = j/2;
                    k++;
                }
                j++;
            }

            i++;    
            if(fgets(line, 2*G->Num + 1, FilePtr) == NULL)
                if(i < G->Num)
                    printf("fgets error 2!\n"); 
        }

        free(line);
    }

    fclose(FilePtr);
}

void GPrint(const tGraphPtr G)
{
    int j, k;

    printf("Graph demonstration:\n");
    for(j = 0; j < G->Num; j++)
    {
        printf("I'm Node: %d , my degree is: %d and my neighbours are:\t", G->Nodes[j]->Val, G->Nodes[j]->Deg);
        for(k = 0; k < G->Nodes[j]->Deg; k++)
            printf("%3d", G->Nodes[j]->Neigh[k]);
        printf("\n");
    }
}

void GDelete(tGraphPtr G)
{

}

int main(int argc, char *argv[])
{

    tGraphPtr TmpGraph;
    char *FNum;
    FNum = "1";

    TmpGraph = malloc(sizeof *TmpGraph);
    if(TmpGraph == NULL)
    {
        printf("Memory allocation error 5!\n");
        return -1;
    }

    GInit(TmpGraph, FNum);

    GPrint(TmpGraph);


    return(0);  
}

这是我正在读取的文件Graph1.txt。该文件末尾包含换行符。

6
0 1 0 1 0 0
1 0 1 0 1 1
0 1 0 1 1 1
1 0 1 0 0 0
0 1 1 0 0 0
0 1 1 0 0 0

如果您有任何关于如何修复此错误的建议,我们将不胜感激。 顺便说一句,Microsoft VS2013 成功构建了此代码(当在 malloc 之前使用类型转换时)并且运行没有错误。 谢谢。 约翰

最佳答案

您是否尝试从“Graph.txt”的最后一行中删除换行符并运行二进制文件?

此外,您应该对 valgrind 报告的泄漏采取一些措施。检查修改后的代码

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

#define MAXFILENAME 20

typedef struct tNode{
        int Deg;
        int Val;
        int* Neigh;
} *tNodePtr;

typedef struct tGraph{
        int Num;
        tNodePtr* Nodes;
} *tGraphPtr;


void GInit(tGraphPtr G, const char *FNum)
{
        char FileName[MAXFILENAME];
        char *FileNamePrefix = "Graph";
        char *FileNamePostfix = ".txt";
        FILE *FilePtr;
        int FileBrowser;
        int i, j, k, countNeigh;
        char *line;
        char c;

        strcpy(FileName, FileNamePrefix);
        strcat(FileName, FNum);
        strcat(FileName, FileNamePostfix);

        FilePtr = fopen(FileName, "r");

        if(!FilePtr)
                printf("Can't open file \"%s\"\n", FileName);
        else
        {
                if(!fscanf(FilePtr, "%d", &FileBrowser))
                        printf("fscanf error 1!\n");

                G->Num = FileBrowser;
                G->Nodes = calloc(G->Num , sizeof *(G->Nodes));
                if(G->Nodes == NULL)
                {
                        printf("Memory allocation error 1!\n");
                        return;
                }

                for(i = 0; i < G->Num; i++)
                {
                        G->Nodes[i] = malloc(sizeof *(G->Nodes[i]));
                        if(G->Nodes[i] == NULL)
                        {
                                printf("Memory allocation error 2!\n");
                                return;
                        }
                }

                line = malloc((2*G->Num + 1) * sizeof *line );
                if(line == NULL)
                {
                        printf("Memory allocation error 3!\n");
                        return;
                }


                i = 0;
                if(!fscanf(FilePtr, "%c", &c))
                        printf("fscanf error 2!\n");
                if(fgets(line, 2*G->Num + 1, FilePtr) == NULL)
                        printf("fgets error 1!\n");
                while(!feof(FilePtr))
                {
                        countNeigh = 0;
                        j = 0;
                        while(line[j] != '\0')
                        {
                                if(line[j] == '1')
                                        countNeigh++;
                                j++;
                        }
                        G->Nodes[i]->Deg = countNeigh;
                        G->Nodes[i]->Val = i;
                        G->Nodes[i]->Neigh = malloc(countNeigh * sizeof *(G->Nodes[i]->Neigh));
                        if(G->Nodes[i]->Neigh == NULL)
                        {
                                printf("Memory allocation error 4!\n");
                                return;
                        }


                        j = 0;
                        k = 0;
                        while(line[j] != '\0')
                        {
                                if(line[j] == '1')
                                {
                                        G->Nodes[i]->Neigh[k] = j/2;
                                        k++;
                                }
                                j++;
                        }

                        i++;
                        if(fgets(line, 2*G->Num + 1, FilePtr) == NULL)
                                if(i < G->Num)
                                        printf("fgets error 2!\n");
                }

                free(line);
        }

        fclose(FilePtr);
}

void GPrint(const tGraphPtr G)
{
        int j, k;
        int i;

        printf("Graph demonstration:\n");
        for(j = 0; j < G->Num; j++)
        {
                printf("I'm Node: %d , my degree is: %d and my neighbours are:\t", G->Nodes[j]->Val, G->Nodes[j]->Deg);
                for(k = 0; k < G->Nodes[j]->Deg; k++)
                        printf("%3d", G->Nodes[j]->Neigh[k]);
                printf("\n");
        }

        for(i = 0; i < G->Num; i++)
        {
                free (G->Nodes[i]->Neigh);
                free (G->Nodes[i]);
        }

        free (G->Nodes);
}

void GDelete(tGraphPtr G)
{

}

int main(int argc, char *argv[])
{

        tGraphPtr TmpGraph;
        char *FNum;
        FNum = "1";

        TmpGraph = malloc(sizeof *TmpGraph);
        if(TmpGraph == NULL)
        {
                printf("Memory allocation error 5!\n");
                return -1;
        }

        GInit(TmpGraph, FNum);

        GPrint(TmpGraph);

        free (TmpGraph);

        return(0);
}

valgrind 的操作

[sourav@localhost ~]$ gcc -g so_test1.c -o test
[sourav@localhost ~]$ valgrind --leak-check=full ./test 
==23941== Memcheck, a memory error detector
==23941== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==23941== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==23941== Command: ./test
==23941== 
Graph demonstration:
I'm Node: 0 , my degree is: 2 and my neighbours are:      1  3
I'm Node: 1 , my degree is: 4 and my neighbours are:      0  2  4  5
I'm Node: 2 , my degree is: 4 and my neighbours are:      1  3  4  5
I'm Node: 3 , my degree is: 2 and my neighbours are:      0  2
I'm Node: 4 , my degree is: 2 and my neighbours are:      1  2
I'm Node: 5 , my degree is: 2 and my neighbours are:      1  2
==23941== 
==23941== HEAP SUMMARY:
==23941==     in use at exit: 0 bytes in 0 blocks
==23941==   total heap usage: 16 allocs, 16 frees, 533 bytes allocated
==23941== 
==23941== All heap blocks were freed -- no leaks are possible
==23941== 
==23941== For counts of detected and suppressed errors, rerun with: -v
==23941== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 8)
[sourav@localhost ~]$

嗯,我的 Graph.txt 末尾没有有换行符。

关于c - 大小 8 2 的读/写无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20420824/

相关文章:

c - 仍然能够访问已释放的结构

C 指针挫折 EXC_BAD_ACCESS

c - 为什么我缺少终止“字符?

c - Malloc 调用崩溃,但在其他地方工作

c 指向结构体的免费临时指针

c - gcc: "implementation-defined"malloc(0) 是如何定义的?

c - 如何在 Linux 中使用 addr2line 命令?

c - 需要此语法的帮助 : "#define LEDs (char *) 0x0003010"

c - 我释放了一切,但内存泄漏

c - 为什么 Valgrind 报告在 PETSc 中分配 char* 时大小为 8 的无效写入?