Skip to content

Commit 7bcabc6

Browse files
committed
Fix a few more memory leaks
Document more info about the benefits of configuring without pymalloc when running valgrind
1 parent 4aef41f commit 7bcabc6

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

Misc/README.valgrind

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ Misc/valgrind-python.supp. Second, you must do one of the following:
1212
* Uncomment the lines in Misc/valgrind-python.supp that
1313
suppress the warnings for PyObject_Free and PyObject_Realloc
1414

15+
If you want to use Valgrind more effectively and catch even more
16+
memory leaks, you will need to configure python --without-pymalloc.
17+
PyMalloc allocates a few blocks in big chunks and most object
18+
allocations don't call malloc, they use chunks doled about by PyMalloc
19+
from the big blocks. This means Valgrind can't detect
20+
many allocations (and frees), except for those that are forwarded
21+
to the system malloc. Note: configuring python --without-pymalloc
22+
makes Python run much slower, especially when running under Valgrind.
23+
You may need to run the tests in batches under Valgrind to keep
24+
the memory usage down to allow the tests to complete. It seems to take
25+
about 5 times longer to run --without-pymalloc.
26+
27+
1528
Details:
1629
--------
1730
Python uses its own small-object allocation scheme on top of malloc,
@@ -21,7 +34,8 @@ Valgrind may show some unexpected results when PyMalloc is used.
2134
Starting with Python 2.3, PyMalloc is used by default. You can disable
2235
PyMalloc when configuring python by adding the --without-pymalloc option.
2336
If you disable PyMalloc, most of the information in this document and
24-
the supplied suppressions file will not be useful.
37+
the supplied suppressions file will not be useful. As discussed above,
38+
disabling PyMalloc can catch more problems.
2539

2640
If you use valgrind on a default build of Python, you will see
2741
many errors like:

Python/ast.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,8 +1054,12 @@ ast_for_listcomp(struct compiling *c, const node *n)
10541054
return NULL;
10551055
}
10561056

1057-
if (asdl_seq_LEN(t) == 1)
1057+
if (asdl_seq_LEN(t) == 1) {
10581058
lc = comprehension(asdl_seq_GET(t, 0), expression, NULL);
1059+
/* only free the sequence since we grabbed element 0 above */
1060+
if (lc)
1061+
asdl_seq_free(t); /* ok */
1062+
}
10591063
else
10601064
lc = comprehension(Tuple(t, Store, LINENO(ch)), expression, NULL);
10611065

@@ -1222,9 +1226,13 @@ ast_for_genexp(struct compiling *c, const node *n)
12221226
return NULL;
12231227
}
12241228

1225-
if (asdl_seq_LEN(t) == 1)
1229+
if (asdl_seq_LEN(t) == 1) {
12261230
ge = comprehension(asdl_seq_GET(t, 0), expression,
12271231
NULL);
1232+
/* only free the sequence since we grabbed element 0 above */
1233+
if (ge)
1234+
asdl_seq_free(t); /* ok */
1235+
}
12281236
else
12291237
ge = comprehension(Tuple(t, Store, LINENO(ch)),
12301238
expression, NULL);

Python/compile.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,7 +2384,10 @@ compiler_import_as(struct compiler *c, identifier name, identifier asname)
23842384
dot = strchr(src, '.');
23852385
attr = PyString_FromStringAndSize(src,
23862386
dot ? dot - src : strlen(src));
2387+
if (!attr)
2388+
return -1;
23872389
ADDOP_O(c, LOAD_ATTR, attr, names);
2390+
Py_DECREF(attr);
23882391
src = dot + 1;
23892392
}
23902393
}

Python/modsupport.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Py_InitModule4(char *name, PyMethodDef *methods, char *doc,
8282
}
8383
Py_DECREF(v);
8484
}
85+
Py_DECREF(n);
8586
}
8687
if (doc != NULL) {
8788
v = PyString_FromString(doc);

0 commit comments

Comments
 (0)