ASan无法在WSL2上找到内存泄漏。
我使用CMake链接ASan库并传递编译器选项:
cmake_minimum_required(VERSION 3.23)
project(test C)
set(CMAKE_C_STANDARD 17)
add_executable(asan_address
src/main.c
src/LinkedList.c src/LinkedList.h)
target_compile_options(asan_address PRIVATE
-std=c18
-Wall
-Werror
-Wextra
-fsanitize=address
-static-libasan
-fno-omit-frame-pointer
-g
-O3
-lm
)
target_link_options(asan_address PRIVATE -fsanitize=address -static-libasan -fno-omit-frame-pointer)
该代码是一个链表的不完整实现,该链表当前无法释放其节点,因此应该会发生内存泄漏。
我编译代码的步骤:
$> cmake .
$> make asan_address
$> ./asan_address
代码:
#include <stdio.h>
#include "LinkedList.h"
int main() {
LinkedList *ll;
int status = initLinkedList(&ll);
if (status == MALLOC_FAILED) {
return MALLOC_FAILED;
}
int value = 1;
status = addValue(ll, &value);
if (status == MALLOC_FAILED) {
return MALLOC_FAILED;
}
void *valuePointer = getElement(ll, 0);
if (valuePointer == NULL) {
printf("value pointer was nulln");
} else printf("value head node:t%dn", *((int *) valuePointer));
return 0;
}
头文件:
#ifndef PRACT01_LINKEDLIST_H
#define PRACT01_LINKEDLIST_H
#include <stdint.h>
#define SUCCESS 0
#define MALLOC_FAILED -1
#define OUT_OF_BOUNDS_INDEX -2
typedef struct Node {
struct Node *next;
struct Node *prev;
void *value;
} Node;
typedef struct LinkedList {
Node *head;
Node *tail;
uint8_t length;
} LinkedList;
int initLinkedList(LinkedList **);
int addValue(LinkedList *, void*);
void* getElement(LinkedList*, unsigned int);
#endif //PRACT01_LINKEDLIST_H
LinkedList.c文件:
#include "LinkedList.h"
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
int initNode(Node **n) {
*n = malloc(sizeof(Node));
if (*n == NULL) {
return MALLOC_FAILED;
}
(*n)->next = NULL;
(*n)->prev = NULL;
(*n)->value = NULL;
return SUCCESS;
}
int initLinkedList(LinkedList **ll) {
*ll = malloc(sizeof(LinkedList));
if (*ll == NULL) {
return MALLOC_FAILED;
}
(*ll)->length = 0;
(*ll)->head = NULL;
(*ll)->tail = NULL;
return SUCCESS;
}
int addValue(LinkedList *ll, void *value) {
unsigned int size = ll->length;
Node *newNode;
int result = initNode(&newNode);
if (result != SUCCESS) {
return result;
}
newNode->value = value;
if (size == 0) {
ll->head = newNode;
ll->length += 1;
return SUCCESS;
}
Node *last = ll->head;
for (unsigned int i = 0; i < size; i++) {
last = last->next;
}
last->next = newNode;
newNode->prev = last;
ll->length += 1;
return SUCCESS;
}
int addValueIndex(LinkedList *ll, unsigned int index, void *value) {
unsigned int size = ll->length;
Node *newNode;
int result = initNode(&newNode);
if (index > size) {
return OUT_OF_BOUNDS_INDEX;
}
if (index == size) {
return addValue(ll, value);
}
if (index == 0) {
ll->head = newNode;
}
Node *last = ll->head;
for (unsigned int i = 0; i < index; i++) {
last = last->next;
}
if (result == MALLOC_FAILED) {
return MALLOC_FAILED;
}
newNode->value = value;
last->next = newNode;
newNode->prev = last;
ll->length += 1;
return SUCCESS;
}
void *getElement(LinkedList *ll, unsigned int index) {
printf("[DEBUG]tindex:t%dn", index);
unsigned int size = ll->length;
printf("[DEBUG]tsize:t%dn", size);
if (size <= index || size == 0) {
return NULL;
}
Node *current = ll->head;
for (unsigned int i = 0; i < index; i++) {
printf("in for loop");
current = current->next;
}
return current->value;
}
void printLinkedList(LinkedList *list) {
printf("List length:t%d", list->length);
}
内存泄漏的问题,地址清理程序用于检测指针错误,而不是内存泄漏。
要检测内存泄漏,请使用泄漏消毒剂:-fsanitize=leak
。
您可以使用多种消毒剂,方法是用逗号分隔。例如-fsanitize=addres,leak,undefined
以启用地址、泄漏和UB消毒程序。
泄漏消毒剂随地址消毒剂一起提供。要检测内存泄漏,请使用已启用的泄漏消毒剂运行您的应用程序
ASAN_OPTIONS=detect_leaks=1 ./asan_address