3 Usage: search_leaks.py <directory> > log.txt
5 This simple script parses a source directory
6 of one of OpenCV source modules
7 and tries to find cvAlloc, cvCreateMat etc.
8 without corresponding cvFree, cvReleaseMat etc.
9 Information about the suspicious places
10 is printed to standard output.
13 import sys, os, re, glob
15 allocfuncs = [ ('cvAlloc', 'cvFree'),
16 ('cvCreateMatND', 'cvReleaseMatND'),
17 ('cvCreateMat', 'cvReleaseMat'),
18 ('cvCreateImage', 'cvReleaseImage'),
19 ('cvCreateHist', 'cvReleaseHist'),
20 ('cvCreateSparseMat', 'cvReleaseSparseMat'),
21 ('cvCreateMemStorage', 'cvReleaseMemStorage'),
22 ('cvCreateChildMemStorage', 'cvReleaseMemStorage'),
23 ('icvIPPFilterInit', 'cvFree'),
24 ('icvFilterInitAlloc', 'icvFilterFree'),
25 ('icvSobelInitAlloc', 'icvFilterFree'),
26 ('icvScharrInitAlloc', 'icvFilterFree'),
27 ('icvLaplaceInitAlloc', 'icvFilterFree'),
28 ('icvSmoothInitAlloc', 'icvSmoothFree'),
29 ('icvMorphInitAlloc', 'icvMorphFree'),]
31 if len(sys.argv) != 2:
37 glob_expr = sys.argv[1] + '/*.c*'
38 for srcname in glob.glob(glob_expr):
43 for l in f.xreadlines():
45 if len(l)>1 and l[0] not in " \t/":
47 # analyze the allocation map
49 for (name,p) in allocdict.items():
51 print "%s(%d): function %s: %s is not deallocated" % \
52 (srcname, lineno, fname, name)
54 if fname == "cvAlloc" or re.findall( "^i?cv(Create)|(Read)|(Clone)", fname ):
56 print "%s(%d): function %s: some of leaks are probably false alarms" % \
57 (srcname, lineno, fname)
58 falsealarms += leaks - leaks0
61 #print "%s(%d): clearing map..." % (srcname, lineno)
63 m = re.findall( r'(\bi?cv\w+)\(', l )
67 #print "%s(%d): clearing map..." % (srcname, lineno)
68 # that's a small speedup that might fail
69 # if create/release naming convention is not used for some structure
70 elif l.find( 'Alloc') >= 0 or l.find('Create') >= 0 or l.find('Init') >= 0:
72 m = re.findall( r'\b' + i[0] + r'\s*\(', l )
74 m = re.findall( r'[\s\(\*]([\w\.\->\[\]]+)\s*=[^=]', l )
76 print "%s(%d): function %s: no variable found in create function" % \
77 (srcname, lineno, fname)
79 #assert (m and m[0]) # if "create" is called,
80 # # there should be a target pointer
81 allocdict[m[0]] = (i[1],1)
83 # the same notice as for cvAlloc & cvCreate
84 elif l.find( 'Free') >= 0 or l.find('Release') >= 0:
86 m = re.findall( r'\b' + i[1] + r'\s*\(', l )
88 m = re.findall( r'([\w\.\->\[\]]+)[\s\)]+;', l )
89 #assert (m and m[0]) # if "release" is called,
90 # # there should be a released pointer (last argument)
92 print "%s(%d): function %s: no variable found in release function" % \
93 (srcname, lineno, fname)
95 p = allocdict.get(m[0],("",0))
97 print "%s(%d): function %s: unmatching release of %s" % \
98 (srcname, lineno, fname, m[0])
100 #assert (p[0] == i[1]) # "release" function should match
101 # # the "create" function used
102 allocdict[m[0]] = (p[0],p[1]-1)
107 print "Result: %d potential leaks found, %d out of them are possible false alarms" % (leaks, falsealarms)