2

嗨,我遇到了 munmap_chunk(): invalid pointer: error in my c 程序。

主要问题是......我什至不确定指针可能变为无效的所有方式是什么。我已经检查了我的代码中没有足够空间调用的字符串,但没有发现任何看起来会超出界限的东西!

相关代码如下(无论如何我认为是相关代码)

//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: _IO_file_xsputn@@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== 
4

1 回答 1

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);

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

所以我认为你需要改变:

print_string_len = strlen(user_string) + 3;

到:

print_string_len = strlen(print_string) + strlen(user_string) + 3;
于 2012-11-30T01:17:38.440 回答