[[!meta copyright="Copyright © 2010 Free Software Foundation, Inc."]] [[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable id="license" text="Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled [[GNU Free Documentation License|/fdl]]."]]"""]] memstat ======= Lists all the processes, executables, and shared libraries that are using up virtual memory. It's helpful to see how the shared memory is used and which 'old' libs are loaded. **Home page**: [[http://sourceforge.net/projects/memstattool]] [[!toc startlevel=2]] * * * Log --- * **Started**: 2012-01-20 * **Discussed**: [2012-01-21](http://lists.debian.org/debian-hurd/2012/01/msg00081.html) * **Draft Submitted**: [2012-01-25](http://lists.debian.org/debian-hurd/2012/01/msg00122.html) * **Submitted**: - * **Accepted**: - * * * ToDo ---- Here is the output of `grep -R PATH_MAX memstat-0.9/*`: memstat.c: char *p, major[8], minor[8], buff[PATH_MAX + 300], *path, perm[4]; memstat.c: char linkname[PATH_MAX], filename[PATH_MAX]; memstat.c: if ((len = readlink(filename, linkname, PATH_MAX)) == -1) { * * * Comments -------- Here are comments on the patch... +#define FMT_PROC_MAPS "/proc/%d/maps" +#define FMT_PROC_EXE "/proc/%d/exe" Define string formats. static void read_proc(void) { unsigned int nread, pid; unsigned long inode, lo, hi, offs; - char *p, major[8], minor[8], buff[PATH_MAX + 300], *path, perm[4]; + char *p, major[8], minor[8], *path, perm[4]; + char *buff = NULL; + size_t buff_size = 0; In this function we turn `buff` into dynamically allocated string. - sprintf(buff, "/proc/%d/maps", pid); - f = fopen(buff, "r"); + char filename[sizeof(FMT_PROC_MAPS) + (sizeof(int) * 3) + 1]; + sprintf(filename, FMT_PROC_MAPS, pid); + f = fopen(filename, "r"); Compute the maximum size of `filename` using `sizeof(int) * 3` as explainend in the [[porting guide|porting_guide_for_dummies]]. - while (fgets(buff, sizeof(buff), f)) { + while (!feof(f)) { + buff = get_line(f); + if (buff == NULL) + break; Read a line from the file using [[get_line()|porting_guide_for_dummies]]. - if ((strlen(buff) == 10) && (strcmp(buff, " (deleted)") == 0)) + if ((strlen(buff) == 10) && (strcmp(buff, " (deleted)") == 0)) { + free(buff); continue; + } nread = sscanf(buff, "%lx %lx %4s %lx %s %s %lu %as", &lo, &hi, perm, &offs, major, minor, &inode, &path); + free(buff); Free the `buff` when it's not used anymore. + buff_size = 4; /* size of the format string without "%x" expressions */ + buff_size += strlen(major); + buff_size += strlen(minor); + buff_size += sizeof(int) * 3 + 1; /* inode */ + buff_size += 1; /* '\0' */ + buff = malloc(buff_size); + if (buff == NULL) { + perror("Cannot allocate memory!"); + exit(1); + } Compute the size that the `buff` must have. - char linkname[PATH_MAX], filename[PATH_MAX]; - ssize_t len; + char *linkname = NULL; + struct stat sb; + ssize_t len = -1; In this function we turn linkname into dynamically allocated string. filename will be declared later. - sprintf(filename, "/proc/%d/exe", pid); - if ((len = readlink(filename, linkname, PATH_MAX)) == -1) { + char filename[sizeof(FMT_PROC_EXE) + (sizeof(int) * 3) + 1]; + sprintf(filename, FMT_PROC_EXE, pid); Same as above with `FMT_PROC_MAPS`. + if (lstat(filename, &sb) == -1) { + perror("lstat"); + deleted = 1; + } + else { + linkname = malloc(sb.st_size + 1); + if (linkname == NULL) { + fprintf(stderr, "insufficient memory\n"); + deleted = 1; + } + else { + len = readlink(filename, linkname, sb.st_size + 1); + } + } + if (len < 0 || len > sb.st_size) { fprintf(stderr, "Cannot read link information for %s\n", filename); deleted = 1; } - linkname[len] = '\0'; + else { + linkname[sb.st_size] = '\0'; + } Use `readlink()` as explained in the porting guide. Require lstat to get the link size. + free(linkname); Free dynamically allocated variable that is not used anymore.