使用fsanitize = address的C内存泄漏

时间:2018-10-06 17:13:15

标签: c pointers makefile memory-leaks

我正在尝试编写一些代码来创建排序的链表,并仅插入唯一元素,以使链表保持排序。另外,我实现了一个删除具有给定值的节点并打印该节点的功能。

我有一些必须运行的测试用例,并且测试软件需要main.c文件和一个makefile,并且在makefile中需要使用fsanitize = address。

没有它,测试用例可以通过,但是将其包含在makefile中,代码将退出并显示消息

  

“摘要:AddressSanitizer:4个分配中泄漏了64个字节。”

或类似的东西。它表明有些是直接泄漏,有些是间接泄漏。

这是我编写的更新的代码

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

/* Link list node */
struct Node {
    int val;
    struct Node* next;
};

void ins(struct Node** head, struct Node* node, int* len) {
    // check if the val held by the head is equal to the new node's val
    // if it is, return
    if(*head != NULL && (*head)->val == node->val) {
        free(node);
        return;
    }

    /* Special case for the head end */
    if (*head == NULL || (*head)->val > node->val) {
        node->next = *head;
        *head = node;
        // increase the length
        (*len)++;
        return;
    } else {
        struct Node* current = *head;
        /* Locate the node before the point of insertion */
        while (current->next != NULL && current->next->val <= node->val) {
            current = current->next;
        }
        // if the node's val is equal to the val of the node
        // in which position it should be inserted, return
        if(node->val == current->val) {
            return;
        }
        // add the node into the linked list
        node->next = current->next;
        current->next = node;
        // increment the list's length
        (*len)++;
    }
}

// delete the value from the linked list
void del(struct Node **head, int value, int* len) {
    // Store head node
    struct Node* temp = *head;

    // If head node itself holds the value to be deleted
    if (temp != NULL && temp->val == value) {
        // change the head
        *head = temp->next;
        // decrease the length
        (*len)--;
        // free the memory and return
        free(temp);
        return;
    }

    struct Node* prev;
    // Search for the key to be deleted, keep track of the
    // previous node as we need to change 'prev->next'
    while(temp != NULL && temp->val != value) {
        prev = temp;
        temp = temp->next;
    }

    // If key was not present in linked list, return
    if(temp == NULL) {
        return;
    }

    // delete the node from the list
    prev->next = temp->next;
    // decrease length
    (*len)--;
    free(temp);  // Free memory
}

void printList(struct Node *head, int len) {
    printf("%d :", len);
    struct Node *temp = head;
    // print the list's content
    while(temp != NULL) {
        printf(" %d", temp->val);
        temp = temp->next;
    }
    printf("\n");
}

int main() {
    /* Start with an empty list and a temporary node */
    struct Node* head = NULL;
    struct Node* temp;
    int len = 0;

    char c;
    int value;
    // while the input is valid
    while(1) {

        // check that there is still input
        if(scanf(" %c", &c) != 1) {
        break;
        }

        // break out of the loop if the first character is other than i and d
        if(c != 'i' && c != 'd') {
        break;
        }

        // read the value
        if(scanf("%d", &value) != 1) {
        break;
        }

        // do the required operations
        if(c == 'i') {
            temp = (struct Node*) malloc(sizeof(struct Node));
            // put in the val and set the next to null
            temp->val  = value;
            temp->next =  NULL;
            ins(&head, temp, &len);
        } else if(c == 'd') {
            del(&head, value, &len);
        }

        // print the list
        printList(head, len);
    }
    free(head);
    return 0;
}

我尝试修复一些内存泄漏,但似乎仍然存在。我最好的猜测是我正在ins()函数中为某些指针分配内存,并且在使用它们后没有释放内存...我尝试在使用某些指针之后释放内存,但这会导致代码出现另一个问题。 >

编辑:这是一些使用了输入的图像以及我得到的实际“错误”。

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

请注意,第三个示例没有内存泄漏,将通过测试用例。

1 个答案:

答案 0 :(得分:0)

-fsanitize = address做什么?

-fsanitize = address (这似乎是valgrind的替代方法,尽管我不确定程度如何)检测到内存泄漏并在程序退出后报告该错误。

没有此标志(-fsanitize = address),将不检查内存泄漏;这解释了为什么在不带标志的情况下编译程序时测试通过并没有内存泄漏摘要的情况。

什么原因导致泄漏?

在程序中,内存泄漏有两个原因。

第一个原因

如果程序在插入一些元素之后退出并且没有显式删除(在每个元素上调用 del())插入的元素,则会导致内存泄漏。

例:
i
99
i
101
i
100
q
修复:在 main()
if(c != 'i' && c != 'd') {
// external inject
    temp = head;
    while(temp) {
        head = head->next;
        free(temp);
        temp = head;
    }
    return 0;
}

第二个原因

如果将同一元素插入两次,则第二次插入将失败(保留了唯一性属性),但是未释放分配的内存,则会导致内存泄漏。

例:
i
99
i
99
d
99
q
修复:在 ins()
if(*head != NULL && (*head)->val == node->val) {
    // external inject
    free(node);
    return;
}
.
.
.
if(node->val == current->val) {
    // external inject
    free(node);
    return;
}

有关-fsanitize=address

的更多信息