2012-11-29 53 views
2

嗨我遇到了一个munmap_chunk():无效的指针:在我的C程序错误。写入无效 - Valgrind

主要问题是...我甚至不知道指针可能会失效的所有方法。我已经检查了我的代码中没有足够空间的字符串,但没有发现任何看起来会超出边界的字符串!

相关的代码如下(我的想法是反正的相关代码)

//Takes in a username and suggests friends of friends who are the opposite sex as friends of username 
395 void suggest_friends(char* username, FILE* out) { 
396  //printf("ENTER suggest_friends\n"); 
397  to_lowercase(username); 
398 
399  if (check_username(username) == 0) { 
400 
401   struct user_node *user = search_username(username); 
402   if (user != NULL) { 
403 
404    struct friend_node *a_friend = user->a_friend; 
405    struct friend_node *friends_friend = NULL; 
406    struct friend_node *temp_friends_friend = NULL; 
407 
408    struct friend_suggest_node *list = NULL; 
409    struct friend_suggest_node *list_it = NULL; 
410    struct friend_suggest_node *new_suggest = NULL; 
411    int friend_suggest_switch = -1; 
412 
413    int print_string_size = 50; 
414    int print_string_len = 0; 
415    char* print_string = calloc(print_string_size + 1, sizeof(char)); 
416    char* user_string = NULL; 
417    int num_suggestions = 0; 
418    int num_mutual_friends = 0; 
419    int max_friends = 0; 
420 
421    //Iterate over all friends 
422    while (a_friend != NULL) { 
423 
424     friends_friend = a_friend->user->a_friend; 
425     //Does friend have friends of opposite sex that I'm not friends with? 
426     //Iterate over friend's friends 
427     while (friends_friend != NULL) { 
428 
429      num_mutual_friends = 0; 
430      //mutual friend found 
431       //Different gender, and not friends 
432      if (friends_friend->user->gender != user->gender && are_friends(friends_friend->u ........ser, user) != 0) { 
433 
434       //are there are elements in the suggested friends list yet?? 
435       if (list == NULL) { 
436 
437        new_suggest = malloc(sizeof(struct friend_suggest_node)); 
438        new_suggest->user = friends_friend->user; 
439        new_suggest->next = NULL; 
440        list = new_suggest; 
441        friend_suggest_switch = 0; 
442       } 
443       //there are already elements 
444       else { 
445 
446        friend_suggest_switch = 0; 
447        //Loop over suggested friends, to check if friends friend already found 
448        list_it = list; 
449        while (list_it != NULL) { 
450 
451         //if the user is already in the suggested list 
452         if (list_it->user == friends_friend->user) { 
453          friend_suggest_switch = -1; 
454          break; 
455         } 
456         list_it = list_it->next; 
457        } 
458 
459        //if the friend to suggest is a new suggestion 
460        if (friend_suggest_switch == 0) { 
461 
462         //add friend to suggest to the front of the list 
462         //add friend to suggest to the front of the list 
463         new_suggest = malloc(sizeof(struct friend_suggest_node)); 
464         new_suggest->user = friends_friend->user; 
465         new_suggest->next = list; 
466         list = new_suggest; 
467        } 
468       } 
469 
470       //if the friend found was new 
471       if (friend_suggest_switch == 0) { 
472 
473        //INTENTION? LOOP OF THE FRIEND OF A FRIEND'S FRIEND LIST!? 
474        //Loop over the remainder of the user's friends's, friend list 
475         //whom is about to be suggested as a mutual friend 
476        temp_friends_friend = friends_friend->user->a_friend; 
477        while (temp_friends_friend != NULL) { 
478 
479         //if user is found who is a mutual friend with user 
480         if (are_friends(temp_friends_friend->user, user) == 0) { 
481 
482          num_mutual_friends++; 
483         } 
484 
485         temp_friends_friend = temp_friends_friend->next_friend; 
486        } 
487 
488        //if more mutual friends then previous choice, 
489         //set user_string equal to this user now 
490        if (num_mutual_friends > max_friends) { 
491         max_friends = num_mutual_friends; 
492        } 
493 
494        //get string for user 
495        user_string = get_user_string(friends_friend->user); 
496        num_suggestions++; 
497        //+3 for \0 and ', ' 
498        print_string_len = strlen(user_string) + 3; 
498        print_string_len = strlen(user_string) + 3; 
499 
500        //if length exceeds size of string 
501        if (print_string_len > print_string_size) { 
502 
503         while (print_string_len >= print_string_size) { 
504          print_string_size *= 2; 
505         } 
506 
507         char* temp_string = calloc(print_string_size + 1, sizeof(char)); 
508         strcpy(temp_string, print_string); 
509         free(print_string); 
510         print_string = temp_string; 
511         temp_string = NULL; 
512        } 
513 
514        //add ", " fot string for formatting 
515        if (strlen(print_string) > 0) { 
516         strcat(print_string, ", \0"); 
517         //TBR 
518         //printf("AFTER TACKING ON COMMA!\n"); 
519        } 
520        strcat(print_string, user_string); 
521        //TBR 
522        //fprintf(out, "before fail 111\n"); 
523        //fprintf(out, "user_string is %s\n", user_string); 
524        //fprintf(out, "user_string ptr is %p\n", user_string); 
525        free(user_string); 
526        //TBR 
527        //fprintf(out, "after fail 111???\n"); 
528        user_string = NULL; 
529       } 
530      } 
531 
532      friends_friend = friends_friend->next_friend; 
533     } 
534 
535     a_friend = a_friend->next_friend; 
536    } 
537 
538    if (num_suggestions != 0) { 
539     fprintf(out, "%s may know following people because they have %d mutual friend(s):\n%s ........\n", username, max_friends, print_string); 
540    } 
541    else { 
542     fprintf(out, "Sorry, there are no friend suggestions for %s.\n", username); 
543    } 
544 
545    free(print_string); 
546    print_string = NULL; 
547   } 
548   else { 
549    fprintf(out, "User %s does not exist. Please try again.\n", username); 
550   } 
551  } 
552  else { 
553   fprintf(out, "%s username is not a valid username\n", username); 
554  } 
555  //printf("EXIT suggest_friends\n"); 
556 } 



//Takes a user_node and returns a char* to a string holding the user's info 
771  //in the format name/age/gender/location 
772 char* get_user_string(struct user_node *user) { 
773  char age[5]; 
774  sprintf(age, "%d", (user->age)); 
775  char* gender = NULL; 
776 
777  //Female 
778  if (user->gender == 0) { 
779   gender = "female\0"; 
780  } 
781  //male 
782  else { 
783   gender = "male\0"; 
784  } 
785 
786  //allocate memory for length of location, name, age, and gender + 3 '/'s + \0 
787   //+20 for good measure!!! 
788  char* user_string = NULL; 
789  user_string = calloc((strlen(user->name) + strlen(user->location) + strlen(age) + strlen(gender)  ........+ 4 + 20), sizeof(char)); 
790  strcat(user_string, user->name); 
791  strcat(user_string, "/"); 
792  strcat(user_string, age); 
793  strcat(user_string, "/"); 
794  strcat(user_string, gender); 
795  strcat(user_string, "/"); 
796  strcat(user_string, user->location); 
797  return user_string; 
798 } 

当我运行它通过Valgrind的,我得到这样的输出:

==10158== Memcheck, a memory error detector 
==10158== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==10158== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==10158== Command: ./social_network -f crash_tester.txt crash_test_output.txt 
==10158== 
==10158== Invalid write of size 1 
==10158== at 0x402C36B: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==10158== by 0x804A434: suggest_friends (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804B25A: command_read (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049460: read_args_file (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049294: switch_parsing (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804ACF7: main (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== Address 0x41f12bb is 0 bytes after a block of size 51 alloc'd 
==10158== at 0x402A5E6: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==10158== by 0x804A1F3: suggest_friends (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804B25A: command_read (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049460: read_args_file (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049294: switch_parsing (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804ACF7: main (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== 
==10158== Invalid write of size 1 
==10158== at 0x402C390: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==10158== by 0x804A434: suggest_friends (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804B25A: command_read (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049460: read_args_file (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049294: switch_parsing (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804ACF7: main (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== Address 0x41f12cf is not stack'd, malloc'd or (recently) free'd 
==10158== 
==10158== Invalid read of size 1 
==10158== at 0x4089E29: vfprintf (vfprintf.c:1630) 
==10158== by 0x4091EBE: fprintf (fprintf.c:33) 
==10158== by 0x804B25A: command_read (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049460: read_args_file (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049294: switch_parsing (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804ACF7: main (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== Address 0x41f12bb is 0 bytes after a block of size 51 alloc'd 
==10158== at 0x402A5E6: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==10158== by 0x804A1F3: suggest_friends (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804B25A: command_read (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049460: read_args_file (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049294: switch_parsing (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804ACF7: main (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== 
==10158== Invalid read of size 4 
==10158== at 0x40C40BC: __GI_mempcpy (mempcpy.S:60) 
==10158== by 0x40B6769: [email protected]@GLIBC_2.1 (fileops.c:1350) 
==10158== by 0x4089E01: vfprintf (vfprintf.c:1630) 
==10158== by 0x4091EBE: fprintf (fprintf.c:33) 
==10158== by 0x804B25A: command_read (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049460: read_args_file (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049294: switch_parsing (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804ACF7: main (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== Address 0x41f12bb is 0 bytes after a block of size 51 alloc'd 
==10158== at 0x402A5E6: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==10158== by 0x804A1F3: suggest_friends (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804B25A: command_read (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049460: read_args_file (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x8049294: switch_parsing (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== by 0x804ACF7: main (in /home/ethan/cs2506/comp-org-3/social_network) 
==10158== 
+0

每个'strcat'调用之前添加'assert'检查,以确保两个字符串的长度之和,加上终止符的一个字节,不大于分配的字节数。我敢打赌,你的“断言”将会发射。 –

回答

1

我相信这个问题是在这里:

print_string_len = strlen(user_string) + 3; 

//if length exceeds size of string 
if (print_string_len > print_string_size) { 

    while (print_string_len >= print_string_size) { 
     print_string_size *= 2; 
    } 

    char* temp_string = calloc(print_string_size + 1, sizeof(char)); 
    strcpy(temp_string, print_string); 
    free(print_string); 
    print_string = temp_string; 
    temp_string = NULL; 
} 

//add ", " fot string for formatting 
if (strlen(print_string) > 0) { 
    strcat(print_string, ", \0"); 
} 
strcat(print_string, user_string); 

当您尝试根据缓冲区限制预先检查最终结果长度时,th e最终结果长度计算不正确。您忘记了包含缓冲区的预先存在的内容;例如strlen(print_string)

所以我认为你需要改变:

print_string_len = strlen(user_string) + 3; 

到:

print_string_len = strlen(print_string) + strlen(user_string) + 3;