Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
memory_leaks.py
Go to the documentation of this file.
1# This file is part of the Ansel project.
2# Copyright (C) 2022 Aurélien PIERRE.
3#
4# Ansel is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# Ansel is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with Ansel. If not, see <http://www.gnu.org/licenses/>.
16#
17#
18#
19#
20#
21#
22#
23#
24#
25#
26#
27# Read each IOP file, parse it for buffer allocs, and check if we have a corresponding free
28#
29import os
30import re
31directory = "../src/iop/"
32
33alloc_regex = r"([a-zA-Z0-9_\->\.\[\]]+) = (dt_|c|m|dt_opencl_)alloc.*\‍(.+\‍)"
34
35
36def find_call_and_line(elem, file, directory):
37 line_number = 0
38 f = open(os.path.join(directory, file), "r")
39
40 # find the line(s) in file
41 for line in f:
42 line_number += 1
43 if elem in line:
44 print("\t\t line", line_number, ":", elem.strip())
45
46 f.close()
47
48for file in sorted(os.listdir(directory)):
49 if file.endswith(".c") or file.endswith(".h"):
50 f = open(os.path.join(directory, file), "r")
51 content = f.read()
52
53 # Find all allocs and extract the name of the pointer to the allocation
54 matches = re.finditer(alloc_regex, content, re.MULTILINE)
55
56 safe_allocs = 0
57 faulty_allocs = 0
58 suspicious_allocs = 0
59
60 print("%s" % file)
61
62 for matchNum, match in enumerate(matches):
63 # Get the name of the pointer to the allocation
64 variable_name = match.group(1)
65 alloc_type = match.group(2)
66
67 # Look how many times the variable is allocated
68 variable_alloc_regex = " %s = %salloc.*\‍(.+\‍)" % (variable_name, alloc_type)
69 matches2 = re.findall(variable_alloc_regex, content, re.MULTILINE)
70 allocs = len(matches2)
71 matches2 = set(matches2)
72
73 # Look how many times the variable is freed
74 variable_free_regex = r""
75 buffer_type = ""
76 if(alloc_type == "dt_opencl_"):
77 variable_free_regex = ".*release_mem_object.*\‍(%s\‍)" % variable_name
78 buffer_type = "OpenCL"
79 else:
80 variable_free_regex = " \S*free.*\‍(%s\‍)" % variable_name
81 buffer_type = "C"
82 matches3 = re.findall(variable_free_regex, content, re.MULTILINE)
83 frees = len(matches3)
84 matches3 = set(matches3)
85
86 # Note that for OpenCL, we may have more than one free for each alloc because of the error go-to
87 if(frees < allocs and frees == 0):
88 print("\tERROR: %s buffer `%s` is allocated %i time(s) but never freed" % (buffer_type, variable_name, allocs))
89 for elem in matches2:
90 find_call_and_line(elem, file, directory)
91 for elem in matches3:
92 find_call_and_line(elem, file, directory)
93
94 faulty_allocs += 1
95
96 elif(frees < allocs and frees > 0):
97 print("\tWARNING: %s buffer `%s` is allocated %i time(s) but freed %i time(s)" % (buffer_type, variable_name, allocs, frees))
98 for elem in matches2:
99 find_call_and_line(elem, file, directory)
100 for elem in matches3:
101 find_call_and_line(elem, file, directory)
102
103 suspicious_allocs += 1
104
105 else:
106 safe_allocs += 1
107
108 msg_type = "INFO"
109 if(suspicious_allocs > 0):
110 msg_type = "WARNING"
111 if(faulty_allocs > 0):
112 msg_type = "ERROR"
113
114 print("\t%s: %i safe alloc(s) detected over %i\n" % (msg_type, safe_allocs, safe_allocs + faulty_allocs + suspicious_allocs))
115
116 f.close()
if(L< 0.5f) C
find_call_and_line(elem, file, directory)