[我将PID放入数组中,并且valgrind告诉我超出范围或分配的内存太少

问题描述 投票:0回答:1

我坚持使用valgrind这个问题来报告我的代码。我正在将PID添加到全局数组(这样做是因为我想在信号处理程序中打印PID)。

Valgrind似乎对将PID放入数组的代码行有问题:

PIDs[number_of_PIDs] = cPID;

这是我的代码:

pid_t *process_ids; //these need to be global b/c they're used in handler for signal
int process_count = 0; //total number of ACTIVE PIDs

void funct() {
     //doing unrelated stuff
     int status;
     rc = fork();
     if(rc==-1) {
          //error
     }
     else if(rc==0) {
          //child (this runs first b/c I used sleep on parent)
          rc=getpid();
          //execvp call
          //if execvp fails, kill child process
     }
     else {
          sleep(1);
     }
     wpid = waitpid(-1, &status, WNOHANG));
     if(wpid==0||WIFEEXITED(status)) {
          PIDs[i]=rc;
          i++;
     } else {
          //printf statement; PID doesn't get added to list
     }
}

220 int main()
221 {
222     //LOCAL VARIABLES
223     gettimeofday(&start_time, NULL); //for calculating total time elapsed
224     FILE *fp; //file pointer for opening 'PID.conf' file
225     //char *process = malloc(sizeof(char)*PATH_MAX); //each process stored here
226     char *process_line;
227     size_t len_buffer = 0;
228     char **args = NULL; //array of char * containing the parsed cmds
229     struct sigaction old; //for handling SIGINT
230     memset(&old, 0, sizeof(old)); //initialize sigaction struct
231     int total_processes; //store total no. of lines for mem allocation of PIDs
232     char *process = NULL;
233     char *token;
234     //test for macD.conf file; if doesn't exist, exit program
235     config_exists();
236
237     //count # of processes
238     total_processes = count_total_processes(); //count no. of processes
239     printf("Total Processes: %d\n", total_processes);
240     process_ids = malloc(sizeof(pid_t)*(total_processes)); //mem for PIDs
241     memset(process_ids, -1, sizeof(pid_t)*total_processes);
242
243     fp = fopen("PID.conf", "r");
244     if(fp == NULL)
245     {
246         printf("error: PID.conf file failed to open. terminating...\n");
247         exit(1);
248     }
249     //free(process_ids);
250     //free(process);
251
252     //check for Ctrl+c and handle it
253     old.sa_handler = &handler; //struct old = handler() funct
254     sigaction(SIGINT, &old, NULL); //catches SIGINT (Ctrl+C)
255
256     //char *token; //storage for each token
257     int arg_size = 0; //store # of args
258
259     //grab each line and process the process
260     while((getline(&process, &len_buffer, fp)) != -1)
261     {
262         arg_size = 0;
263         process_line = (char*)malloc(PATH_MAX*sizeof(char)); //allocate
264         process_line[strlen(process)-1] = 0; //remove newline
265         strcpy(process_line, process); //copied to get non-edited version from strtok
266         token = strtok(process, " ");
267
268         //count number of tokens=path/cmd+args
269         while(token!=NULL) {
270             token = strtok(NULL, " ");
271             arg_size++;
272         }
273
274         //parse the process into the individual cmd and its args
275         process_line[strlen(process_line)-1] = 0;//remove newline from cmd
276         strcpy(process, process_line); //copied cmd to print it later
277         //args = malloc(sizeof(char*)*(arg_size+1));
278         args = funct2(process_line, arg_size); //command to actually parse cmd
279
280         //execute the cmd by creating a fork() + exec() call
281         funct(args, process, args[0]);
282
283         //free process_line as not needed
284         free(process_line);
285         int i;
286         for(i=0;i<arg_size;i++)
287         {
288             free(args[i]);
289         }
290         free(args);
291     } //END OF WHILE LOOP FOR PARSING FILE
292     free(process);
293     //free(process_ids); //free later!
294     fclose(fp); //close file, won't need it anymore
295
296     //check each successful process in array process_ids every 5s
297     while(1)
298     {
299         sleep(5); //sleep for 5s
300         check_status(process_ids); //pass PID array to print status
301     }
302
303     return 0;
304 }

valgrind错误如下:

==6310== LEAK SUMMARY:
==6310==    definitely lost: 0 bytes in 0 blocks
==6310==    indirectly lost: 0 bytes in 0 blocks
==6310==      possibly lost: 0 bytes in 0 blocks
==6310==    still reachable: 24 bytes in 1 blocks
==6310==         suppressed: 0 bytes in 0 blocks
==6310== Reachable blocks (those to which a pointer was found) are not shown.
==6310== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==6310==
==6310== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==6310==
==6310== 1 errors in context 1 of 1:
==6310== Invalid write of size 4
==6310==    at 0x4010F3: funct
==6310==    by 0x401496: main
==6310==  Address 0x51db388 is 0 bytes after a block of size 24 alloc'd
==6310==    at 0x4C2A0B0: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==6310==    by 0x40134F: main
==6310==
==6310== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

我做错什么了吗?还是在哪里寻找valgrind错误有其他建议?

编辑:我为PID的总数分配内存,但是我还要检查每个PID是否处于活动/运行状态。仅将那些活动的添加到阵列中。

c arrays valgrind dynamic-memory-allocation pid
1个回答
0
投票

地址0x51db388是在分配大小为24的块之后的0字节

没有办法是“ 8”个PID。 24除以8就是3,而pid_t几乎可以肯定是4。

您可能分配了六个pid_t的空间,但是以某种方式最终使用了九个(包括0到8)。我对为什么在块后写入zero字节而不是eight字节感到困惑,但我敢肯定问题出在您的number_of_PIDs常量中。

关于PID为何看起来可以正确打印的原因,在数组末尾进行写入是未定义的行为。如果没有人使用那里的内存,没有人(例如valgrind)检查等等,那么您可以在那儿写并读回您写的内容,它将起作用。 但是没有保证。而且,编写的内容越多,其他事物(例如malloc库)需要该内存或将其检出的风险就越大,从而导致严重的故障。甚至更糟的是,随机故障可能很难跟踪并且非常耗时。

© www.soinside.com 2019 - 2024. All rights reserved.