nano-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nano-devel] 1.0.8 Memory leaks . . . and fixes


From: Steven Kneizys
Subject: [Nano-devel] 1.0.8 Memory leaks . . . and fixes
Date: Sun, 17 Feb 2002 13:30:30 -0800 (PST)

I got a copy of 'zmalloc' on the web, and made changes, additions,
corrections (fixed a bug in a debugging tool! ;-)  Zmalloc basically
uses macros to redefine standard memory calls to be redirected to its
own routines that keep track of the calls to allocate and free memory.
It reports such things as re-freeing a previously freed buffer and
unfreed buffers and mild buffer over(under)runs.

Two of the things I added to zmalloc were the realloc and getcwd
functions, and created zmalloc-friendly versions of some of the utils
routines.  It originally reported the source of memory allocations as
the utils routines, and I needed to know where those routines were
being called.  

I hooked it up to 1.1.1, it helped me find the 'null_at' bug that has
been previously fixed for example, as well as many other leaks.  I
hooked it up to 1.0.8 and found lots of leaks.  After some tweaking of
the code I got all of the ones I observed fixed, there may be more ;-)

I created a routine 'thanks_for_the_memories' that does cleanup at the
end, perhaps it should be called at other places when nano leaves in
error (last thing called, couldn't hurt maybe?)

HTH,

Steve...

__________________________________________________
Do You Yahoo!?
Yahoo! Sports - Coverage of the 2002 Olympic Games
http://sports.yahoo.com
diff -u -b -r nano-1.0.8/files.c nano-1.0.8.new/files.c
--- nano-1.0.8/files.c  Wed Oct 24 07:42:21 2001
+++ nano-1.0.8.new/files.c      Sun Feb 17 15:20:44 2002
@@ -279,13 +279,17 @@
            char *tmp = do_browse_from(realname);
 
 #ifdef DISABLE_TABCOMP
+           if (realname != NULL) free(realname);
            realname = NULL;
 #endif
-           if  (tmp != NULL)
+           if  (tmp != NULL) {
                realname = mallocstrcpy(realname, tmp);
-           else
+               free(tmp);
+           } else {
+               if (realname != NULL) free(realname);
                return do_insertfile();
        }
+       }
 #endif
 
        i = open_file(realname, 1, 0);
@@ -325,11 +329,11 @@
 int write_file(char *name, int tmp)
 {
     long size, lineswritten = 0;
-    static char *buf = NULL;
+    char *buf = NULL;
     filestruct *fileptr;
     int fd, mask = 0, realexists, anyexists;
     struct stat st, lst;
-    static char *realname = NULL;
+    char *realname = NULL;
 
     if (!strcmp(name, "")) {
        statusbar(_("Cancelled"));
@@ -338,12 +342,6 @@
     titlebar(NULL);
     fileptr = fileage;
 
-    if (realname != NULL)
-       free(realname);
-
-    if (buf != NULL)
-       free(buf);
-
 #ifndef DISABLE_TABCOMP
     realname = real_dir_from_tilde(name);
 #else
@@ -357,8 +355,13 @@
     anyexists = lstat(realname, &lst);
 
     /* New case: if the file exists, just give up */
-    if (tmp && anyexists != -1)
+    if (tmp && anyexists != -1) {
+       if (realname != NULL) 
+           free(realname);
+       if (buf != NULL)
+           free(buf);
        return -1;
+    }
     /* NOTE: If you change this statement, you MUST CHANGE the if 
        statement below (that says:
                if (realexists == -1 || tmp || (!ISSET(FOLLOW_SYMLINKS) &&
@@ -374,6 +377,10 @@
 
        /* First, just give up if we couldn't even open the file */
        if (fd == -1) {
+           if (realname != NULL) 
+               free(realname);
+           if (buf != NULL)
+               free(buf);
            if (!tmp && ISSET(TEMP_OPT)) {
                UNSET(TEMP_OPT);
                return do_writeout(filename, 1);
@@ -390,6 +397,10 @@
        strncpy(buf, realname, strlen(realname)+1);
        strcat(buf, ".XXXXXX");
        if ((fd = mkstemp(buf)) == -1) {
+           if (realname != NULL) 
+               free(realname);
+           if (buf != NULL)
+               free(buf);
            if (ISSET(TEMP_OPT)) {
                UNSET(TEMP_OPT);
                return do_writeout(filename, 1);
@@ -427,12 +438,20 @@
        if (size == -1) {
            statusbar(_("Could not open file for writing: %s"),
                      strerror(errno));
+           if (realname != NULL) 
+               free(realname);
+           if (buf != NULL)
+               free(buf);
            return -1;
        } else if (size > 0) {
            size = write(fd, "\n", 1);
            if (size == -1) {
                statusbar(_("Could not open file for writing: %s"),
                          strerror(errno));
+               if (realname != NULL) 
+                   free(realname);
+               if (buf != NULL)
+                   free(buf);
                return -1;
            }
        }
@@ -442,6 +461,10 @@
     if (close(fd) == -1) {
        statusbar(_("Could not close %s: %s"), realname, strerror(errno));
        unlink(buf);
+       if (realname != NULL) 
+           free(realname);
+       if (buf != NULL)
+           free(buf);
        return -1;
     }
 
@@ -466,6 +489,10 @@
                statusbar(_("Could not open %s for writing: %s"),
                          realname, strerror(errno));
                unlink(buf);
+               if (realname != NULL) 
+                   free(realname);
+               if (buf != NULL)
+                   free(buf);
                return -1;
            }
        }
@@ -475,11 +502,19 @@
            statusbar(_("Could not open %s for writing: %s"),
                      name, strerror(errno));
            unlink(buf);
+           if (realname != NULL) 
+               free(realname);
+           if (buf != NULL)
+               free(buf);
            return -1;
        } else if (rename(buf, realname) == -1) {       /* Try a rename?? */
            statusbar(_("Could not open %s for writing: %s"),
                      realname, strerror(errno));
            unlink(buf);
+           if (realname != NULL) 
+               free(realname);
+           if (buf != NULL)
+               free(buf);
            return -1;
        }
     }
@@ -493,6 +528,10 @@
        UNSET(MODIFIED);
        titlebar(NULL);
     }
+    if (realname != NULL) 
+       free(realname);
+    if (buf != NULL)
+       free(buf);
     return 1;
 }
 
@@ -1077,7 +1116,7 @@
 {
     int i;
 
-    for (i = 0; i < len - 1; i++)
+    for (i = 0; i < len; i++)
        free(array[i]);
     free(array);
 }
@@ -1116,7 +1155,10 @@
     if (tmp != foo)
        *tmp = 0;
     else
+    { /* SPK may need to make a 'default' path here */
+        if (*tmp != '/') *(tmp) = '.';
        *(tmp+1) = 0;
+    }
 
     return;
 }
@@ -1245,6 +1287,17 @@
            else
                path = mallocstrcpy(path, filelist[selected]);
 
+           /* SPK for '.' path, get the current path via getcwd */
+           if (!strcmp(path, "./..")) {
+               free(path);
+               path = getcwd(NULL, 0);
+               striponedir(path);                  
+               align(&path);
+               free_charptrarray(filelist, numents);
+               free(foo);
+               return do_browser(path);
+           }
+
            st = filestat(path);
            if (S_ISDIR(st.st_mode)) {
                if (opendir(path) == NULL) {
@@ -1264,6 +1317,8 @@
                }
 
                /* Start over again with the new path value */
+               free_charptrarray(filelist, numents);
+               free(foo);
                return do_browser(path);
            } else {
                retval = path;
@@ -1359,6 +1414,8 @@
     /* cleanup */
     free_charptrarray(filelist, numents);
     free(foo);
+    if (path != NULL) free(path);
+    path = NULL;
     return retval;
 }
 
@@ -1368,6 +1425,7 @@
 {
     struct stat st;
     char *tmp = NULL;
+    int ret;
 
     tmp = mallocstrcpy(tmp, inpath);
 
@@ -1379,20 +1437,27 @@
 #else
        char *from = getcwd(NULL, 0);
 #endif /* PATH_MAX */
-       return do_browser(from ? from : "./");
+        if (tmp != NULL) free(tmp); 
+       ret = do_browser(from ? from : "./");
+        if (from != NULL) free(from); 
+       return ret;
     }
 
     /* If the string is a directory, pass do_browser that */
     st = filestat(tmp);
-    if (S_ISDIR(st.st_mode))
-       return do_browser(tmp);
+    if (S_ISDIR(st.st_mode)){
+       ret = do_browser(tmp);
+       free(tmp);
+       return ret;
+    }
 
     /* Okay, there's a dir in there, but not at the end of the string... 
        try stripping it off */
     striponedir(tmp);
     align(&tmp);
-    return do_browser(tmp);
-
+    ret = do_browser(tmp);
+    free(tmp);
+    return ret;
 }
 
 
diff -u -b -r nano-1.0.8/nano.c nano-1.0.8.new/nano.c
--- nano-1.0.8/nano.c   Tue Jan 15 19:54:35 2002
+++ nano-1.0.8.new/nano.c       Sun Feb 17 15:21:15 2002
@@ -101,6 +101,8 @@
     /* Restore the old term settings */
     tcsetattr(0, TCSANOW, &oldterm);
 
+    thanks_for_the_memories();
+
     exit(sigage);
 }
 
@@ -2827,5 +2829,44 @@
 
     getchar();
     finish(0);
+
+}
+/* added by SPK for memory cleanup */
+void thanks_for_the_memories(void) 
+{
+/* SPK plug some leaks! */
+ /*   if (operating_dir != NULL)
+       free(operating_dir);/* needed later */
+    if (last_search != NULL)
+       free(last_search);
+    if (last_replace != NULL)
+       free(last_replace);
+    if (hblank != NULL)
+       free(hblank);
+    if (alt_speller != NULL)
+       free(alt_speller);
+    if (help_text != NULL)
+       free(help_text);
+    if (filename != NULL)
+       free(filename);
+    if (answer != NULL)
+       free(answer);
+#ifdef ENABLE_MULTIBUFFER
+    if (open_files != NULL){
+        while (open_files->next != NULL) {
+           open_files = open_files->next;
+           free_filestruct(open_files->prev);
+        }
+        free_filestruct(open_files);
+    }
+#endif
+#ifndef ENABLE_MULTIBUFFER
+    if (fileage != NULL)
+        free_filestruct(fileage);
+#endif
+    if (cutbuffer != NULL)
+        free_filestruct(cutbuffer);
+
+    /* that is all for now */
 
 }

diff -u -b -r nano-1.0.8/proto.h nano-1.0.8.new/proto.h
--- nano-1.0.8/proto.h  Fri Jan 11 08:51:38 2002
+++ nano-1.0.8.new/proto.h      Sun Feb 17 13:56:52 2002
@@ -65,6 +80,7 @@
 
 /* Programs we want available */
 
+void thanks_for_the_memories(void);
 char *strcasestr(char *haystack, char *needle);
 char *strstrwrapper(char *haystack, char *needle);
 int search_init(int replacing);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]