The program reads the proc file system, namely, it must read the stat process files. At me on 3 processes everything falls on segmentation fault. Falls on fopen () when fopen calls malloc; I can not understand what's wrong.

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <string.h> #include <dirent.h> #include <stdbool.h> #include <errno.h> #define MAX_LENGTH_FILENAME 120 typedef struct proc_info { int pid; char *name; int ppid; } proc_info; typedef struct Node { proc_info *info; struct Node *next; struct Node *prev; } Node; typedef struct List { size_t size; struct Node *head; struct Node *tail; } List; List *createList() { List *tmp = (List *) malloc (sizeof(List)); tmp->head = NULL; tmp->tail = NULL; tmp->size = 0; return tmp; } void copy_proc_info(proc_info *dst, const proc_info *src) { size_t len = strlen(src->name); dst->pid = src->pid; dst->ppid = src->ppid; dst->name = (char *) malloc(len + 1); if (NULL == dst->name) { fprintf(stderr,"Error get new memory.\nNot create new char*!\n"); } else { strncpy(dst->name, src->name, len + 1); } } void push_back(List *list, const proc_info *info) { int rezult = 0; Node *tmp = (Node *) malloc(sizeof(Node)); if (NULL == tmp) { fprintf(stderr,"Error get new memory.\nNot create new Node!\n"); return; } tmp->next = NULL; tmp->prev = list->tail; copy_proc_info(tmp->info, info); if (list->tail) { list->tail->next = tmp; } list->tail = tmp; if (list->head == NULL) { list->head = tmp; } list->size++; } bool cat_stat_file(const char *dir_name, struct proc_info *info) { errno = 0; bool rezult = false; char buf[MAX_LENGTH_FILENAME+1+11]; sprintf(buf, "/proc/%s/stat", dir_name); printf("%s", buf); FILE *f = fopen(buf, "r"); //погибает здесь на 3 вызове if (errno && (NULL == f)) { fprintf(stderr, "Error open file %s\n", buf); perror(""); } else { fscanf(f,"%d %s %*c %d", &info->pid, &buf, &info->ppid); printf("%s\n", buf); if (errno) { fprintf(stderr, "Error read file %s.\n", dir_name); perror(""); errno = 0; } else { size_t len = strlen(buf) + 1; info->name = (char *) malloc(len); strncpy(info->name, buf, len); rezult = true; } fclose(f); if (errno) { fprintf(stderr, "Error close file %s.\n", dir_name); perror(""); errno = 0; } } return rezult; } List *get_dir_list(const char *dir_name) { struct proc_info *dir_list = NULL; DIR *dir; struct dirent *entry; List *list = createList(); if ((dir = opendir(dir_name)) == NULL) { fprintf(stderr, "Error opendir %s\n", dir_name); perror(""); errno = 0; return NULL; } while ( (entry = readdir(dir)) != NULL) { if (errno) { fprintf(stderr, "Error read_dir %s\n", dir_name); perror(""); errno = 0; continue; } if ( (entry->d_type != DT_DIR) || (strlen(entry->d_name) > 5) || !strtol(entry->d_name, NULL, 0)) {continue;} proc_info *info = (struct proc_info *) malloc(sizeof(proc_info)); if (cat_stat_file(entry->d_name, info)) push_back(list, info); else free(info); }; return list; } int main() { List *list = get_dir_list("/proc"); //destroyList(&list); return 0; } 
  • The memory you have previously allocated is spoiling somewhere (for example, writing more than what you have allocated) or making free twice of the same block. - avp
  • @avp to free does not even reach. here and break my head. valgrind says the following == 10101 == 1 errors in context 1 of 2: == 10101 == Invalid write of size 4 == 10101 == at 0x804889F: copy_proc_info (in /home/super/step/parent/a.out) == 10101 == by 0x804896E: push_back (in /home/super/step/parent/a.out) == 10101 == by 0x8048CBE: get_dir_list (in /home/super/step/parent/a.out) == 10101 == by 0x8048D0F: main (in /home/super/step/parent/a.out) == 10101 == Address 0x0 is not stack'd, malloc'd or (recently) free'd but not enough experience to understand it all. I am just learning. - rubeno4ka
  • Size MAX_LENGTH_FILENAME may be too small? It’s better for paths to use PATH_MAX , defined in stdlib.h (more precisely in /usr/include/linux/limits.h , but it is pulled up via stdlib ). / Dynamically allocate proc_info clearly superfluous. This information can be placed immediately in the Node / The process name may contain spaces (you have already asked for something like this), but fortunately, it is enclosed in brackets. It is better to read the entire file (or rather its only line) fgets() and localize the name there by calling strchr / strrchr to search for parentheses. ppid can then be read by sscanf , from the right bracket. - avp

1 answer 1

In the push_back function, you forgot to allocate memory for tmp->info .

 tmp->next = NULL; tmp->prev = list->tail; tmp->info = (proc_info *) malloc(sizeof(proc_info)); // <----- здесь copy_proc_info(tmp->info, info); 
  • List * get_dir_list (const char * dir_name) {...... proc_info * info = (struct proc_info *) malloc (sizeof (proc_info)); if (cat_stat_file (entry-> d_name, info)) push_back (list, info); else free (info); } @kmv it is highlighted in get_dir_list, and the pointer is passed to push_back - rubeno4ka
  • @ rubeno4ka for info memory allocated, I agree, but under tmp->info - no. - kmv
  • sure you are right thank you. now the copy_proc_info function is not required in principle. tmp-> info = info. thanks for the help. - rubeno4ka