【问题标题】:Program crashes when malloc executed执行 malloc 时程序崩溃
【发布时间】:2016-12-11 16:39:34
【问题描述】:

当我执行*arr = malloc(i * sizeof(struct cluster_t*)); 时,我的代码不断崩溃。簇是一种结构。 我不确定是什么问题。第二个输入是一个结构数组(簇)它应该将txt文件加载到数组中,每一行作为一个单独的结构第一个输入是一个.txt文件,其中包含:

    count=20
40 86 663
43 747 938
47 285 973
49 548 422
52 741 541
56 44 854
57 795 59
61 267 375
62 85 874
66 125 211
68 80 770
72 277 272
74 222 444
75 28 603
79 926 463
83 603 68
86 238 650
87 149 304
89 749 190
93 944 835

这里是部分代码似乎有问题(我在第一个答案后稍微修改了它)这不是一个完整的代码:

int load_clusters(char *filename, struct cluster_t **arr) //nefunkcne
{
    assert(arr != NULL);

    char buffer_load[256] = {'0'};
    int riadok = 0;
    int count = 0;

    int *X = malloc(sizeof(int));
    if (X == NULL) {
        perror("Chyba mallocu na load_clusters X");
        free(X);
        exit(EXIT_FAILURE);
    }

    int *Y = malloc(sizeof(int));
    if (Y == NULL) {
        perror("Chyba mallocu load_clusters Y");
        free(X);
        free(Y);
        exit(EXIT_FAILURE);
    }

    int *ID = malloc(sizeof(int));
    if (ID == NULL) {
        perror("Chyba mallocu v load_clusters ID");
        free(X);
        free(Y);
        free(ID);
        exit(EXIT_FAILURE);
    }

    FILE *subor = fopen(filename, "r");
    if (subor == NULL) {
        perror("Chyba nacitania suobru fopen load_clusters!");
    }

    while (fgets(buffer_load, sizeof buffer_load, subor) != NULL) {
        if (riadok > 0) {
            struct cluster_t shluk;
            sscanf(buffer_load,"%d %d %d", ID, X, Y);
            init_cluster(&shluk, 1);
            struct obj_t objekt;
            objekt.id = *ID;
            objekt.x = *X;
            objekt.y = *Y;

            append_cluster(&shluk, objekt);

            arr[riadok - 1] = malloc(sizeof(struct cluster_t*));
            if (arr[riadok-1] == NULL) {
                perror("Chyba mallocu v load_clusters 388!");
                free(arr[riadok - 1]);
                exit(EXIT_FAILURE);
            }

            (*arr)[riadok - 1] = shluk;
        } else {
            sscanf(buffer_load, "count=%d", &count);
            *arr = malloc(count * sizeof(struct cluster_t));
            if (arr == NULL) {
                perror("Chyba mallocu v load_clusters 400!");
                free(*arr);
                exit(EXIT_FAILURE);
            }
        }
        riadok++;
    }

    fclose(subor);
    free(X);
    free(Y);
    free(ID);
    return cout;
}

我保持最新的完整代码(请记住使用 `-std=c99 -Wextra -Wall -Werror -DNDEBUG 和 -lm 如果在 gcc 中,因为数学库): https://docs.google.com/document/d/1xoNcBpY1lkmki3-E5WUYFVg-xojjvEkUJ63XC_UzhtM/edit?usp=sharing

【问题讨论】:

  • 评论不用于扩展讨论;这个对话是moved to chat
  • 总是很好地显示提到的结构的定义

标签: c crash buffer-overflow callstack


【解决方案1】:

你的代码太复杂,有问题:

  • 您不需要分配数据来传递指向scanf() 的指针,只需传递局部变量的地址即可。
  • 查看scanf()的返回值:返回成功转换的次数。如果转换失败,则不会设置相应的变量,其余的转换也会失败。
  • 如果您的 txt 文件以 count=20 等空格开头,scanf 格式应包含一个初始空格以使用这些空格:" count=%d"
  • 指针和结构之间似乎存在很多混淆:函数应该分配簇数组还是将对象序列加载到分配的簇中?

这是一个将对象加载到单个分配的集群中的简化版本:

int load_clusters(const char *filename, struct cluster_t **arr) {
    char buffer_load[256];
    int riadok, count, X, Y, ID;
    struct cluster_t *cp;

    assert(arr != NULL);

    // Open the input file
    FILE *subor = fopen(filename, "r");
    if (subor == NULL) {
        perror("Chyba nacitania suobru fopen load_clusters!");
        exit(EXIT_FAILURE);
    }

    // Read and parse the count line
    if (fgets(buffer_load, sizeof buffer_load, subor) == NULL ||
        sscanf(buffer_load, " count=%d", &count) != 1) {
        perror("missing count line in file\n");
        fclose(subor);
        exit(EXIT_FAILURE);
    }

    // allocate and initialize the cluster
    *arr = cp = malloc(sizeof(**arr));
    if (cp == NULL) {
        perror("Chyba mallocu v load_clusters 400!");
        exit(EXIT_FAILURE);
    }
    init_cluster(cp, count);

    riadok = 0;
    while (riadok < count &&
           fgets(buffer_load, sizeof buffer_load, subor) != NULL) {
        if (sscanf(buffer_load,"%d %d %d", &ID, &X, &Y) == 3) {
            struct obj_t objekt;
            objekt.id = ID;
            objekt.x = X;
            objekt.y = Y;
            append_cluster(cp, objekt);
            riadok++;
        }
    }

    fclose(subor);
    return riadok;
}

【讨论】:

    【解决方案2】:

    以下代码编译干净,但由于缺少子函数而无法链接。

    警告:我无法测试代码,因此不能 100% 确定它会正常工作。

    #include <stdio.h>  // fopen(), fclose(), fgets()
    #include <stdlib.h> // exit(), EXIT_FAILURE, malloc()
    #include <assert.h> // assert()
    #include <string.h> // strchr()
    
    struct cluster_t
    {
    };
    
    struct obj_t
    {
        int id;
        int x;
        int y;
    };
    
    void init_cluster(struct cluster_t*, int );
    void append_cluster(struct cluster_t*, struct obj_t*);
    
    int load_clusters(char *filename, struct cluster_t **arr) //nefunkcne
    {
        assert(arr != NULL);
    
        char buffer_load[256] = {'0'};
        int riadok = 0;
        int i = 0;
    
        int X;
        int Y;
        int ID;
    
        FILE *subor = NULL;
        if( NULL == (subor = fopen(filename, "r") ) )
        {
            perror("Chyba nacitania suobru fopen load_clusters!");
            exit( EXIT_FAILURE );
        }
    
        // implied else, fopen successful
    
        // initialize for number of struct instances
        if( ! fgets( buffer_load, sizeof( buffer_load ), subor ) )
        {
            fprintf( stderr, "unable to read first line from input file\n" );
            exit( EXIT_FAILURE );
        }
    
        char *token = NULL;
        if( NULL == (token = strchr( buffer_load, '=' ) ) )
        {
            fclose( subor );
            exit( EXIT_FAILURE );
        }
    
        else
        { // else delimeter found
            token++; // step past '='
            i = atoi( token );
    
            // allocate array of pointers to 'struct cluster_t'
            if( NULL == (*arr = malloc( (size_t)i * sizeof(struct cluster_t*) ) ) )
            {
                perror("Chyba mallocu v load_clusters 400!");
                fclose( subor );
                exit(EXIT_FAILURE);
            }
    
            // implied else, malloc successful
        }
    
    
        while( riadok < i && fgets( buffer_load, sizeof buffer_load, subor) )
        {
            struct cluster_t shluk;
            sscanf(buffer_load,"%d %d %d", &ID, &X, &Y);
    
            init_cluster(&shluk, 1);
    
            struct obj_t objekt;
            objekt.id = ID;
            objekt.x  = X;
            objekt.y  = Y;
            append_cluster(&shluk, &objekt);
    
            if( NULL == ( arr[riadok] = malloc(sizeof(struct cluster_t)) ) )
            {
                perror("Chyba mallocu v load_clusters 388!");
                fclose( subor );
    
                for( int j=0; j<riadok; j++ )
                {
                    free(arr[j]);
                }
    
                exit(EXIT_FAILURE);
            }
    
            memcpy( arr[riadok], &shluk, sizeof( struct cluster_t ) );
    
            riadok++;
        }
    
        fclose(subor);
    
        return i;
    }
    

    【讨论】:

    • 我发布了完整的代码,以及 gcc 的自定义设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2016-11-27
    相关资源
    最近更新 更多