Viewing file: leak-4.c (2.58 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* Various tests of memory leak detection. */
#include <stdlib.h>
/* Example of an leak due to incomplete cleanup when freeing a struct. */
struct s1 { void *ptr; };
void test_1 (void) { struct s1 *a = malloc (sizeof (struct s1)); if (!a) return; a->ptr = malloc (1024); /* { dg-message "allocated here" } */ free (a); /* { dg-warning "leak of '<unknown>'" } */ /* TODO: we should print "a->ptr' here, rather than '<unknown>' (PR analyzer/99771). */ }
/* Examples involving arrays. */
struct s2 { void *m_arr[10]; };
void test_2a (void) { struct s2 arr[5]; arr[3].m_arr[4] = malloc (1024); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'arr\\\[3\\\].m_arr\\\[4\\\]'" } */
void test_2b (int i) { struct s2 arr[5]; arr[3].m_arr[i] = malloc (1024); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'arr\\\[3\\\].m_arr\\\[i\\\]'" } */
void test_2c (int i) { struct s2 arr[5]; arr[i].m_arr[4] = malloc (1024); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'arr\\\[i\\\].m_arr\\\[4\\\]'" } */
void test_2d (int i, int j) { struct s2 arr[5]; arr[i].m_arr[j] = malloc (1024); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'arr\\\[i\\\].m_arr\\\[j\\\]'" } */
/* Example involving fields. */
struct s3 { struct s3 *m_left; struct s3 *m_right; };
void test_3 (void) { struct s3 *a = malloc (sizeof (struct s3)); a->m_right = malloc (sizeof (struct s3)); /* { dg-warning "dereference of possibly-NULL 'a'" } */ a->m_right->m_left = malloc (sizeof (struct s3)); /* { dg-warning "dereference of possibly-NULL '\\*a.m_right'" } */ } /* { dg-warning "leak of 'a'" "leak of a" } */ /* { dg-warning "leak of '<unknown>'" "leak of unknown" { target *-*-* } .-1 } */ /* TODO: rather than '<unknown>', we should print 'a->m_right' and 'a->m_right->m_left' (PR analyzer/99771). */
/* Example involving faking inheritance via casts. */
struct s4_base { int m_placeholder; };
struct s4_sub { void *m_buffer; };
static struct s4_sub * make_s4_sub (void) { struct s4_sub *sub = malloc (sizeof (struct s4_sub)); /* { dg-message "allocated here" } */ if (!sub) return NULL; sub->m_buffer = malloc (1024); /* { dg-message "allocated here" } */ return sub; }
void test_4 (void) { struct s4_base *base = (struct s4_base *)make_s4_sub (); } /* { dg-warning "leak of 'base'" "leak of base" } */ /* { dg-warning "leak of '<unknown>'" "leak of sub buffer" { target *-*-* } .-1 } */ /* TODO: rather than 'unknown', we should print something like '((struct s4_sub *)base)->m_buffer' (PR analyzer/99771). */
|