双免费/腐败?

时间:2013-09-16 23:51:28

标签: c malloc free

typedef struct {
    int *info;
} row;

struct {
    row* head;
    int len;
    int size;
} list;

int main{
    list.len = 0;
    list.size = 1;
    list.head = malloc(list.size * sizeof(row));
    //...... some other code that calls addRow (list.len) times
    for (i = list.len - 1; i > 0; i--) {
        free(list.head[i].info);/*****HERE**********/
    }
    free(list.head);
    }

void addRow(int* data) {
    int i;
    if (list.len == list.size) {
        row *temp = malloc(sizeof(row) * list.size * 2);
    if (temp == NULL) {
        fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
        return;
    }
    for (i = 0; i < list.len; i++) {
        temp[i] = list.head[i];
    }
    free(list.head);
    list.head = temp;
    }
    list.head[list.len].info = malloc(sizeof(int) * numCols);
    for (i = 0; i < numCols; i++) {
        list.head[list.len].info[i] = data[i];
    }
    list.len++;

}

这是我用来addRow的代码是我malloc的所有数据。而且我不明白为什么我会遇到双重免费/损坏错误。在我标记为HERE的区域,我相信我正在对行结构中的所有信息实例进行malloc-ing,这些行是唯一执行malloc / free的。

我只是想在终止程序时养成正确的习惯。

完整计划:

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

typedef struct {
    int *info;
} row;

struct {
    row* head;
    int len;
    int size;
} list;

static int sortCol, numCols;

int qSortCompare(const void*, const void*);
void printList();
int processInput();
void nullify(char*, int);

int main(int n, char **args) {
    sortCol = 1;
    numCols = 0;
    if (n > 1 && args[1][0] == '-' && args[1][1] == 'c') {
        sortCol = atoi(args[2]);
    }
    list.len = 0;
    list.size = 1;
    list.head = malloc(list.size * sizeof(row));
    processInput();
    if (sortCol < 1 || sortCol > numCols) {
        fprintf(stderr, "Error (enter): (Line ##) Invalid column to sort.\n");
        return 1;
    }
    printList();
    qsort(list.head, list.len, sizeof(row), &qSortCompare);
    printf("\n");
    printList();
    int i;
    printf("add1:%p\nadd2:%p\n", list.head[0].info, list.head[1].info);
    for (i = 0; i < list.len; i++) {
        free(list.head[i].info);
    }
    free(list.head);
    return 0;
}

void nullify(char* str, int n) {
    int i;
    for (i = 0; i < n; i++)
        str[i] = '\0';
}

int parseInt(char *str, int index) {
    int num = -1;
    sscanf(str + index, "%d", &num);
    return num;
}

void addRow(int* data) {
    int i;
    if (list.len == list.size) {
        row *temp = malloc(sizeof(row) * list.size * 2);
        if (temp == NULL) {
            fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
            return;
        }
        for (i = 0; i < list.len; i++) {
            temp[i] = list.head[i];
        }
        free(list.head);
        list.head = temp;
    }
    list.head[list.len].info = malloc(sizeof(int) * numCols);
    if (list.head[list.len].info == NULL) {
        fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
        return;
    }
    for (i = 0; i < numCols; i++) {
        list.head[list.len].info[i] = data[i];
    }
    list.len++;
}

int processInput() {
    int i, maxChars = 200, totalN = 0;
    int *nums, curNumIndex = 0, onNum, curNum;
    numCols = maxChars / 2;
    nums = (int*) (malloc(sizeof(int) * numCols));
    char str[maxChars], ch;
    for (i = 0; i < numCols; i++) {
        nums[i] = -1;
    }
    while (!feof(stdin)) {
        nullify(str, maxChars);
        fgets(str, maxChars, stdin);
        onNum = isdigit(str[0]);
        curNumIndex = 0;
        for (i = 0; i < maxChars; i++) {
            ch = str[i];
            if ((!isspace(ch)) && (!isdigit(ch)) && (ch != '\0')) {
                fprintf(stderr, "Error 1: (Line ##) Invalid char in input.\n");
                //return 0;
            }
            if (isspace(ch) && onNum) {
                curNum = parseInt(str, curNumIndex);
                curNumIndex = i;
                nums[totalN % numCols] = curNum;
                totalN++;
                if (totalN % numCols == 0)
                    addRow(nums);
            } else {
                onNum = isdigit(str[i]);
            }
            if (ch == '\n' || ch == '\0')
                break;
        }
        if (numCols > totalN) {
            if (totalN > 0) {
                numCols = totalN;
                addRow(nums);
            } else {
                fprintf(stderr,
                        "Error (enter): (Line ##) Invalid first line of input.\n");
            }
        }
        if (ch != '\n' && ch != '\0') {
            fprintf(stderr,
                    "Error (enter): (Line ##) A row from input too long.\n");
            //return 0;
        }
    }

    return 1;
}

int qSortCompare(const void *c1, const void *c2) {
    row *t1, *t2;
    t1 = (row*)c1;
    t2 = (row*)c2;
    return t1->info[sortCol - 1] - t2->info[sortCol - 1];
}

void printList() {
    int i, j;
    for (i = 0; i < list.len; i++) {
        for (j = 0; j < numCols; j++) {
            printf("%10d   ", list.head[i].info[j]);
        }
        printf("\n");
    }
}

程序需要EOF终止的整数输入。特别是在换行符之前使用相同数量的整数。

更新:我使用gdb分析免费部分我只在第二次迭代时失败,使用for(i = 0; i < list.len; i++)for(i = list.len - 1; i > 0 ; i--)

2 个答案:

答案 0 :(得分:2)

另一件事是我没有看到list.size的更新(在调整头部时应该更新)

答案 1 :(得分:1)

“我只是想在终止程序时养成正确的习惯。”

处理这类事情的正确方法是释放非NULL指针,然后将指针设置为NULL。

例如:

int* x = malloc (sizeof (int));

if (x != NULL) {
  free (x);
  x = NULL;
}

/* Misc. Code ... */

/* Now for whatever reason, you want to free x again */

/* This branch is never triggered, because you were smart enough to set x to NULL
 *  when you freed it the first time...
 */
if (x != NULL) {
  free (x);
  x = NULL;
}