While testing Vim with Valgrind memory checker,
I encountered this memory leak:
==6498== 183 bytes in 4 blocks are definitely lost in loss record 31 of 43
==6498== at 0x4022765: malloc (vg_replace_malloc.c:149)
==6498== by 0x8113B58: lalloc (misc2.c:862)
==6498== by 0x8093F03: make_filter_cmd (ex_cmds.c:1528)
==6498== by 0x809382E: do_filter (ex_cmds.c:1163)
==6498== by 0x809357D: do_bang (ex_cmds.c:1031)
==6498== by 0x80AE8F5: ex_bang (ex_docmd.c:8335)
==6498== by 0x80A5BDE: do_one_cmd (ex_docmd.c:2623)
==6498== by 0x80A342A: do_cmdline (ex_docmd.c:1099)
==6498== by 0x80A2956: do_exmode (ex_docmd.c:656)
==6498== by 0x8129EAB: nv_exmode (normal.c:5137)
==6498== by 0x8123542: normal_cmd (normal.c:1152)
==6498== by 0x80E6371: main_loop (main.c:1181)
==6498== by 0x80E5EC1: main (main.c:940)
Unfortunately, I'm not sure how to reproduce it. But looking
at the code, it is clear that there is one path where memory
is not freed.
In ex_cmds.c below, local variable cmd_buf is allocated
at line 1163, then freed later at line 1202. But in between,
line 1183 may do "goto error;" which will cause to return
without freeing local variable cmd_buf.
(ex_cmds.c)
1163 cmd_buf = make_filter_cmd(cmd, itmp, otmp); <--------
cmd_buf is allocated here
1164 if (cmd_buf == NULL)
1165 goto filterend;
1166
1167 windgoto((int)Rows - 1, 0);
1168 cursor_on();
1169
1170 /*
1171 * When not redirecting the output the command can write
anything to the
1172 * screen. If 'shellredir' is equal to ">", screen may be messed up by
1173 * stderr output of external command. Clear the screen later.
1174 * If do_in is FALSE, this could be something like ":r !cat", which may
1175 * also mess up the screen, clear it later.
1176 */
1177 if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
1178 redraw_later_clear();
1179
1180 if (do_out)
1181 {
1182 if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL)
1183 goto error; <---------------- LEAK!!!
**************************
1184 redraw_curbuf_later(VALID);
1185 }
1186 read_linecount = curbuf->b_ml.ml_line_count;
1187
1188 /*
1189 * When call_shell() fails wait_return() is called to give the user a
1190 * chance to read the error messages. Otherwise errors are
ignored, so you
1191 * can see the error messages from the command that appear on
stdout; use
1192 * 'u' to fix the text
1193 * Switch to cooked mode when not redirecting stdin, avoids
that something
1194 * like ":r !cat" hangs.
1195 * Pass on the SHELL_DOOUT flag when the output is being redirected.
1196 */
1197 if (call_shell(cmd_buf, SHELL_FILTER | SHELL_COOKED | shell_flags))
1198 {
1199 redraw_later_clear();
1200 wait_return(FALSE);
1201 }
1202 vim_free(cmd_buf); <------------ cmd_buf is freed here
I attach a patch which fixes it.
I'm using vim-7.1.291 on Linux x86.
-- Dominique
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---
Index: ex_cmds.c
===================================================================
RCS file: /cvsroot/vim/vim7/src/ex_cmds.c,v
retrieving revision 1.107
diff -c -r1.107 ex_cmds.c
*** ex_cmds.c 18 Feb 2008 18:42:52 -0000 1.107
--- ex_cmds.c 5 Apr 2008 13:49:26 -0000
***************
*** 1180,1186 ****
--- 1180,1189 ----
if (do_out)
{
if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL)
+ {
+ vim_free(cmd_buf);
goto error;
+ }
redraw_curbuf_later(VALID);
}
read_linecount = curbuf->b_ml.ml_line_count;
***************
*** 4471,4477 ****
/*
* The new text is build up step by step, to avoid too much
* copying. There are these pieces:
! * sub_firstline The old text, unmodifed.
* copycol Column in the old text where we started
* looking for a match; from here old text still
* needs to be copied to the new text.
--- 4474,4480 ----
/*
* The new text is build up step by step, to avoid too much
* copying. There are these pieces:
! * sub_firstline The old text, unmodified.
* copycol Column in the old text where we started
* looking for a match; from here old text still
* needs to be copied to the new text.