簡體   English   中英

C:如何將malloc的指針傳遞給函數並釋放它們?

[英]C: How do I pass malloc'ed pointers into a function and free them?

我正在使用套接字和線程來開發客戶端服務器程序。 我有一個用於客戶端的菜單,並且正在嘗試從客戶端向服務器發送一個字符,然后調用相應的功能。 我正在嘗試使用指針和malloc,但我認為我不太了解如何傳遞它們並釋放它們。 我遇到內存泄漏和類似錯誤:

./server':兩次釋放或損壞(fasttop):0x00007f37dc000a50 ***

分段故障

這是我的客戶菜單:

char *choice = (char*) malloc(sizeof(char));

do {

    // get a string from the server
    get_msg(sockfd);

    printf("\nFile and Information System\n");
    printf("===========================\n");
    printf("1. Show IP and Student ID\n");
    printf("2. Display server time\n");
    printf("3. Display system information\n");
    printf("4. List files on server\n");
    printf("5. File Transfer\n");
    printf("6. Exit\n");
    printf("Enter choice: ");
    scanf("%s", choice);

    //Send input to server
    send_menu_choice(sockfd, choice);

    switch (*choice) 
    {
        case '1':
                get_ip(sockfd);
            break;
        case '2':
                get_time(sockfd);
            break;
        case '3':
                get_and_send_uname(sockfd);
            break;
        case '4':
                get_file_list(sockfd);
            break;
        case '5':
                printf("File transfer not yet implemented\n");;
            break;
        case '6':
                printf("Exiting...\n");
            break;
        default:
                printf("Invalid choice\n");
    }

    //if(menu_choice != NULL)
    //{
    //    free(menu_choice);
    //}

} while (*choice != '6');

if (choice != NULL)
{
    free(choice);
}

將菜單選項發送到服務器:

void send_menu_choice(int socketNumber, char *choice)
{
    printf("Sending menu choice...\n");
    size_t n = strlen(choice) + 1;

    writen(socketNumber, (unsigned char *) &n, sizeof(size_t));
    writen(socketNumber, (unsigned char *) choice, n);

    printf("Sent choice: %s\n\n", choice);
}


服務器端:

char *menu_choice = (char*) malloc(sizeof(char));

do { 

    printf("Waiting for client to select option...\n\n");
    send_msg(connfd);

    get_menu_choice(connfd, menu_choice);
    printf("Client %d choice was: %s\n", connfd, menu_choice);

    switch (*menu_choice) 
    {
        case '1':
                send_ip(connfd);
            break;
        case '2':
                send_time(connfd);
            break;
        case '3':
                get_and_send_uname(connfd, *uts);
            break;
        case '4':
                send_file_list(connfd);
            break;
        case '5':
                printf("File Transfer not implemented\n");
            break;
        case '6': 
            break;
        default:
                printf("Invalid choice\n");
    }

    //if(menu_choice != NULL)
    //{
    //    free(menu_choice);
    //}

} while (*menu_choice != '6');

if (choice != NULL)
{
    free(choice);
}

從客戶端獲取菜單選項:

void get_menu_choice(int socketNumber, char *choice)
{
    size_t n;

    readn(socketNumber, (unsigned char *) &n, sizeof(size_t));  
    readn(socketNumber, (unsigned char *) choice, n);

    printf("Received: %zu bytes\n\n", n);
}


要求的其他功能:

發送消息(服務器端):

 void send_msg(int socket) { char msg_string[] = "\\nPlease enter an option:"; size_t n = strlen(msg_string) + 1; writen(socket, (unsigned char *) &n, sizeof(size_t)); writen(socket, (unsigned char *) msg_string, n); } 

獲取信息(客戶端:

 void get_msg(int socket) { char msg_string[32]; size_t k; readn(socket, (unsigned char *) &k, sizeof(size_t)); readn(socket, (unsigned char *) msg_string, k); printf("%s\\n", msg_string); } 

我在這里做錯了什么? 我不會影響指針指向的位置的值嗎?

do循環中,您反復釋放指針

if(menu_choice != NULL)
{
    free(menu_choice);
}

但是,您只能在循環之前分配一次。

請允許我將循環壓縮到以下關鍵行:

char *choice = (char*) malloc(sizeof(char));

do {

  scanf("%s", choice);
  switch (*choice) {
    case '6':
      printf("Exiting...\n");
      break;
    default:
      printf("Invalid choice\n");
  }

  if (choice != NULL)
  {
    free(choice);
  }

} while (*choice != '6');

此循環存在嚴重缺陷。 您不僅會使用1個字節的內存來存儲2( scanf應該使用%c而不是%s ),而且如果您選擇非6的值,則循環不僅會訪問釋放的內存,而且還會導致雙重釋放(您的錯誤)。 另一方面,如果選擇6,則在釋放內存后正在訪問內存,這也是一個非常嚴重的錯誤。

循環終止后,您應該釋放內存。

服務器端,

char *menu_choice = (char*) malloc(sizeof(char));

您分配一個字符。

然后在get_menu_choice()稱為get_menu_choice(connfd, menu_choice)使用1個字節分配menu_choice

void get_menu_choice(int socketNumber, char *choice)
{
   size_t n;

   readn(socketNumber, (unsigned char *) &n, sizeof(size_t));  
   readn(socketNumber, (unsigned char *) choice, n);

您將n個字節存儲到choice ...

這似乎不正確。

一字節分配足夠了嗎? 意思是, n取值> 1?

這是一個通用答案,這是我在項目中使用的功能:

/* this is safe free() and no not what you asked, check next one */
void my_free(void *ptr)
{
    if (ptr) {
        free(ptr);
    }
}

/* this is almost same as safe free above but also sets the pointer to NULL */
void my_freep(void **ptr)
{
    if (*ptr != NULL) {
        free(*ptr);
    }

    *ptr = NULL;
}

然后像這樣調用my_freep my_freep((void**)&buffer);
注意這里的buffer被定義為指針(即char *buffer; )。
希望能有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM