释放分配的内存会产生分段错误

时间:2015-07-10 09:32:17

标签: c segmentation-fault free

我尝试从文本文件中读取,然后将每个单词放在列表节点中(然后以相反的顺序打印它)。

该程序运行良好,但在尝试释放已分配的列表节点时,程序崩溃。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <math.h>
typedef struct node{
    char* word;
    struct node* next;
}; typedef struct node* list;
void freeall(list lst){
    list temp = NULL;
    while (lst)
    {
        temp = lst->next;
        free(lst);
        lst = temp;
    }
#if 0
    if (lst == NULL){ return; }
    freeall(lst->next);
    free(lst->word);
    free(lst);
#endif // 0

}
void deleteAllNodes(list start)
{
    while (start != NULL)
    {
        list temp = start;
        free(temp);
        start = start->next;
    }
}
list createNode(char* buff){
    list newnode = (list)malloc(sizeof(list));
    assert(newnode);
    newnode->next = NULL;
    newnode->word = (char*)calloc(strlen(buff), sizeof(char));
    assert(newnode->word);
    strcpy(newnode->word, buff);
    return newnode;
}
void reverse(const char *str) //you don't need to modify your string
{
    if (*str != '\0'){ //if the first character is not '\O' 
        reverse((str + 1)); // call again the function but with +1 in the pointer addr
        printf("%c", *str); // then print the character
    }
}
void print_reverse(list lst){
    if (lst == NULL) return;
    print_reverse(lst->next);
    reverse(lst->word);
    //free(lst->word);
}
list createList(FILE* ifp){
    struct node *loop = NULL;
    list curr = NULL;
    list lst = NULL;
    char *word = NULL;
    size_t size = 2;
    long fpos = 0;
    char format[32];
    if (ifp == NULL)        // open file
        perror("Failed to open file \n");
    if ((word = malloc(size)) == NULL)                  // word memory
        perror("Failed to allocate memory");
    sprintf(format, "%%%us", (unsigned)size - 1);        // format for fscanf
    while (fscanf(ifp, format, word) == 1) {
        while (strlen(word) >= size - 1) {                // is buffer full?
            size *= 2;                                  // double buff size
            printf("** doubling to %u **\n", (unsigned)size);
            if ((word = realloc(word, size)) == NULL)
                perror("Failed to reallocate memory");
            sprintf(format, "%%%us", (unsigned)size - 1);// new format spec
            fseek(ifp, fpos, SEEK_SET);                  // re-read the line
            if (fscanf(ifp, format, word) == 0)
                perror("Failed to re-read file");
        }
        curr = createNode(word);
        if (lst == NULL){lst = curr;}
        else{
            loop = lst;
            while (loop->next != NULL) {//loop to last structure
                loop = loop->next;//add structure to end
            }
            loop->next = curr;
        }
        fpos = ftell(ifp);                               // mark file pos
    }
    free(word);
    return lst;
}
int main(int argc, char* argv[]){
        assert(argc == 2);
        FILE *ifp = fopen(argv[1], "r");
        assert(ifp);
        list lst = NULL;
        lst = (list)malloc(sizeof(list));
        lst = createList(ifp);
        print_reverse(lst);
        fclose(ifp);
        //freeall(lst);
        //deleteAllNodes(lst);
        return 1;
    }

3 个答案:

答案 0 :(得分:2)

deleteAllNodes函数中,您正在释放指针然后访问它。您可以尝试以相反的顺序删除节点,从最后一个开始,例如使用递归函数。

void deleteAllNodes(list start)
{
    if (start != NULL)
    {
        deleteAllNodes(start->next);
        free(start);
    }
}

或者您可以坚持使用类似(未经测试)的迭代前向删除:

void deleteAllNodes(list start)
{   
    list previous = NULL;
    while (start != NULL)
    {   
        if (previous != NULL)
            free(previous);
        previous = start;
        start = start->next;
    }
    if (previous != NULL)
        free(previous);
}

答案 1 :(得分:2)

您的$scope.createNewDroplet = function () { $scope.drop.user_id = $scope.user.id; drop.create($scope.drop).success(function(droplet) { $scope.createdDroplet = droplet; }); }; 有错误。你释放了一个指针并尝试立即访问它。程序崩溃你可以尝试这个

delete all nodes

将当前ptr指向头部并指向下一个元素。删除当前指针。

答案 2 :(得分:0)

问题,我认为是

 list newnode = (list)malloc(sizeof(list));

您的liststruct node*的typedef,所以此声明基本上是

list newnode = (list)malloc(sizeof(struct node*));

错误。你为指向结构变量的指针分配内存,而你应该分配内存等于结构变量本身的大小。

这里要提两件事

  1. malloc() Ctypedef家人的回复价值see why not to cast
  2. 永远不要使用list = malloc(sizeof*list); 作为指针类型。这不是一个“规则”,但最好坚持下去。
  3. 您的分配声明至少应为

    main()

    除此之外,在lst函数

    • 首先,您使用malloc()将内存分配给createList() [与上述分配相同的问题]
    • 然后,您分配另一个指针,lst的返回值为malloc()

    这样,您就会通过malloc()覆盖分配的mekory,创建memory leak。你根本不需要docker ps -a