malloc执行时程序崩溃

时间:2016-12-11 16:39:35

标签: c crash buffer-overflow callstack

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

    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

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

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

警告:我无法测试代码,所以不是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;
}