2014-09-29 61 views
-1

下面是我的C程序的一個功能。在下面的函數中,我傳遞了3個字符指針,但我沒有在函數中使用它們。但是,在執行memset()函數後,字符串的值將變爲NULL或GARBAGE。任何人都可以告訴我爲什麼會發生這種情況?memset設置字符指針NULL /垃圾

下面是完整的代碼....請忽略壞的編碼風格爲我的測試代碼:)。

#include <netinet/in.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <strings.h> 
#include <unistd.h> 
#include <sys/poll.h> 


static void * process_request_client(void *arg); 
void getClientInput(int sockfd, char ** ptr_ip_addr, char ** ptr_port_no, char ** ptr_page); 
int split(char * str, char delim, char ***array, int *length); 
int connect_web(char * ip_addr, char * port, char * page); 
void process_webPage(int soc_client, int soc_web, char * page, char * host); 
//############## 

int main (int argc, char **argv) { 
    /* variables section */ 
    pthread_t tid; 
    int    listenfd, connfd; 
    pid_t    childpid; 
    socklen_t   clilen; 
    struct sockaddr_in cliaddr, servaddr; 

    /* creating a socket */ 
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 
    printf("\n%s: Error in socket", argv[0]); 
    exit(0); 
    } 

    /* configuring server address structure */ 
    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_family  = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port  = htons(9876); 

    /* binding our socket to the service port */ 
    if (bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0) { 
    printf("\n%s: Error in bind", argv[0]); 
    exit(0); 
    } 

    /* convert our socket to a listening socket */ 
    if (listen(listenfd, 5) < 0) { 
    printf("\n%s: Error in listen", argv[0]); 
    exit(0); 
    } 

    for (; ;) { 
    clilen = sizeof(cliaddr); 

    /* accept a new connection and return a new socket descriptor to 
    handle this new client */ 
    if ((connfd = accept(listenfd, (struct sockaddr*) &cliaddr, &clilen)) < 0) { 
     printf("\n%s: Error in accept", argv[0]); 
     exit(0); 
    } 

    pthread_create(&tid, NULL, &process_request_client, (void *) connfd); 
    } 
    return 0; 
} 


static void * process_request_client(void *soc_client) { 
    char * ip_addr; 
    char ** ptr_ip_addr; 
    char * port_no; 
    char ** ptr_port_no; 
    char * page; 
    char ** ptr_page; 

    ptr_ip_addr = &ip_addr; 
    ptr_port_no = &port_no; 
    ptr_page = &page; 

    int soc_web; 
    pthread_detach(pthread_self()); 

    getClientInput((int) soc_client,ptr_ip_addr,ptr_port_no,ptr_page); 

    printf("ip_addr in process_request_client -> %s \n port in process_request_client-> %s \n page in process_request_client->%s\n",ip_addr,port_no,page); 

    //create socket connection to web server 
    soc_web = connect_web(ip_addr, port_no, page); 

    printf("ip_addr in process_request_client -> %s \n port in process_request_client-> %s \n page in process_request_client->%s\n",ip_addr,port_no,page); 

    //process webPage 
    //process_webPage((int)soc_client, soc_web, page, ip_addr); 

    printf("ip_addr in process_request_client -> %s \n port in process_request_client-> %s \n page in process_request_client->%s\n",ip_addr,port_no,page); 

    close(soc_web); 
    close((int) soc_client); 
    return (NULL); 
} 

void getClientInput(int sockfd, char ** ptr_ip_addr, char ** ptr_port_no, char ** ptr_page){ 
    ssize_t n; 
    char line[512]; 
    char **res; 
    int rc, count = 0, k=0; 
    /* read from socket */ 
    n = read(sockfd, (void *) line, 512); 

    if (n < 0) { 
     printf("\nError in read"); 
     exit(0); 
    } else if (n == 0) { 
     return; 
    } 
    line[n-1] = NULL; 
    printf("Yo baby got it:%d\n",n); 
    //printf("%s\n",line); 
    //printf("####################################\n"); 


    //split it and store it variables 
    rc = split(line, ':', &res, &count); 
    if(rc) { 
    printf("Error: error in spliting \n"); 
    } 

    *ptr_ip_addr = res[0]; 
    *ptr_port_no = res[1]; 
    *ptr_page = res[2]; 
    printf("in getClientInput ->%s \n",*ptr_ip_addr); 
    printf("in getClientInput ->%s \n",*ptr_port_no); 
    printf("in getClientInput ->%s \n",*ptr_page); 
    //close(sockfd);     //closed here earlier 
} 

int split(char * str, char delim, char ***array, int *length) { 
    char *p; 
    char **res; 
    int count=0; 
    int k=0; 
    int index = 0; 

    do{ 
    //printf("%c\n", str[]); 
    index++; 
    } while (str[index] != NULL); 
    str[index] = ':'; 
    index++; 
    str[index] = NULL; 

    printf("%s--------------------------\n",str); 

    p = str; 
    // Count occurance of delim in string 
    while((p=strchr(p,delim)) != NULL) { 
    *p = 0; // Null terminate the deliminator. 
    p++; // Skip past our new null 
    count++; 
    } 

    // allocate dynamic array 
    res = calloc(1, count * sizeof(char *)); 
    if(!res) return -1; 

    p = str; 
    for(k=0; k<count; k++){ 
    if(*p) res[k] = p; // Copy start of string 
    p = strchr(p, 0); // Look for next null 
    p++; // Start of next string 
    } 

    *array = res; 
    *length = count; 

    return 0; 
} 

int connect_web(char * ip_addr_old, char * port_old, char * page_old) { 

    struct addrinfo hints, *res; 
    int sockfd, retVal; 
    char * ip_addr="www.website.edu"; 
    char * port ="80"; 

    printf("11111..ip_addr in connect_web 1 -> %s \n port in connect_web 2-> %s \n page in connect_web 3->%s\n",ip_addr_old,port_old,page_old); 


    printf("ip_addr in connect_web -> %s \n port in connect_web-> %s \n",ip_addr,port); 
    printf("size= %d\n",strlen(ip_addr)); 

    // first, load up address structs with getaddrinfo(): 
    memset(&hints, 0, sizeof hints); 
    printf("2222222.ip_addr in connect_web 1 -> %s \n port in connect_web 2-> %s \n page in connect_web 3->%s\n",ip_addr_old,port_old,page_old); 

    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    retVal=getaddrinfo(ip_addr, port, &hints, &res); 
    printf("getaddrinfo Return Val is -> %d\n",retVal); 
    // create a socket: 
    printf("33333333.ip_addr in connect_web 1 -> %s \n port in connect_web 2-> %s \n page in connect_web 3->%s\n",ip_addr_old,port_old,page_old); 

    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 
    /* connecting to the server */ 
    //connect(sockfd, res->ai_addr, res->ai_addrlen); 
    printf("444444.ip_addr in connect_web 1 -> %s \n port in connect_web 2-> %s \n page in connect_web 3->%s\n",ip_addr_old,port_old,page_old); 

    if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) { 
    printf("\n: Error in connect to web page"); 
    exit(0); 
    } 
    printf("55555.ip_addr in connect_web 1 -> %s \n port in connect_web 2-> %s \n page in connect_web 3->%s\n",ip_addr_old,port_old,page_old); 

    return sockfd; 

} 
void process_webPage(int soc_client, int soc_web, char * page, char * host){ 
    char arr[200]; 
    char * sendline; 
    char recvline[4096]; 
    int n,rv; 
    struct pollfd ufds[2]; 

    printf("\n%s----------in process_webPage\n",page); 
    printf("\n%s----------in process_webPage\n",host); 

    //ufds[0].fd = s1; 
    //ufds[0].events = POLLIN | POLLPRI; // check for normal or out-of-band 

    ufds[1].fd = soc_web; 
    ufds[1].events = POLLIN; // check for just normal data 

    // Prepare the HTTP request 
    sendline = arr; 
    strcpy(arr,"GET "); 
    strcat(arr,page); 
    strcat(arr," HTTP/1.1\r\nHost:"); 
    strcat(arr,host); 
    strcat(arr,"\r\n\r\n"); 


    /* send it to server */ 
    printf ("%s\n",sendline); 
    if (write(soc_web, (const void*) sendline, strlen(sendline)) < 0) { 
    printf("\n: Error in write to web server socket"); 
    exit(0); 
    } 


    // Receive data from Socket 
    rv = poll(ufds, 2, 3500); 
    /*while (rv > 0) { 
    if (rv == -1) { 
     perror("poll"); // error occurred in poll() 
    } else if (rv == 0) { 
     printf("Timeout occurred! No data after 3.5 seconds.\n"); 
    } else { 
     if (ufds[1].revents & POLLIN) { 
     recv(soc_web, recvline, 4096-1, 0); 
     } 
    } 
    //fputs(recvline, stdout); 
    printf("mmmmmmmmmmmmmmmmmmmm %d", rv); 
    rv = poll(ufds, 2, 3500); 
    }*/ 
    printf("@@@@@@@@@@@@ Out Side @@@@@@@@@@@\n"); 

    close(soc_web); 
} 

這裏是出把

Yo baby got it:37 
www.website.edu:80:/~page/index.html:-------------------------- 
in getClientInput ->www.website.edu 
in getClientInput ->80 
in getClientInput ->/~page/index.html 
ip_addr in process_request_client -> www.website.edu 
port in process_request_client-> 80 
page in process_request_client->/~page/index.html 
11111..ip_addr in connect_web 1 -> www.website.edu 
port in connect_web 2-> 80 
page in connect_web 3->/~page/index.html 
ip_addr in connect_web -> www.utdallas.edu 
port in connect_web-> 80 
size= 16 
2222222.ip_addr in connect_web 1 -> �q�website.edu 
port in connect_web 2-> 80 
page in connect_web 3->/ 
getaddrinfo Return Val is -> 0 
33333333.ip_addr in connect_web 1 -> 
port in connect_web 2-> 
page in connect_web 3-> 
444444.ip_addr in connect_web 1 -> 
port in connect_web 2-> 
page in connect_web 3-> 
55555.ip_addr in connect_web 1 -> �q�webs�PS�`PS� 
port in connect_web 2-> 
page in connect_web 3-> 
ip_addr in process_request_client -> �q�webs�PS�`PS� 
port in process_request_client-> 
page in process_request_client-> 
ip_addr in process_request_client -> �q�webs�PS�`PS� 
port in process_request_client-> 
page in process_request_client-> 
+1

你可以粘貼打印? – 2014-09-29 21:00:47

+0

爲什麼使用'memset'並事​​後手動設置'hints'的某些成員,而不是直接使用struct-initializer並讓編譯器一次完成所有操作?將更短,更可讀... – Deduplicator 2014-09-29 21:02:01

+1

另:保持行長合理。你真的不需要超過80個字符的行!水平滾動是致命的。 – Deduplicator 2014-09-29 21:03:14

回答

1

你的指針ip_addrport_nopage都指向char line[512];這是一個局部變量的getClientInput功能。這個函數返回後,內存被釋放。

你在connect_web症狀發生,因爲內存可重複用於局部變量裏面connect_web;所以修改這些局部變量意味着您的指針指向的char line[512]的內容似乎會改變。

要解決此問題,您可以將其設置爲static char line[512];,或者您可以讓getClientInput函數爲正在「返回」的每個字符串動態分配內存。

但是你的代碼已經相當混亂和難以遵循,這並不奇怪,你有內存錯誤。我會建議做一個包含所有你需要的指針的struct(而不是有一個特設陣列的3個指針,或者函數的參數列表),並確保您一個一個該結構的實例分配一切地點。然後你可以有一個函數來釋放一個完整的結構,一旦你完成了它。

+0

此外,'getClientInput'應該在訪問'res [0]',res [1]','res [2]' – 2014-09-30 01:51:36

+0

之前檢查'count> = 3',感謝@MattMcNabb以找出問題...我移除了所有的指針和指針的指針。相反,我在process_request_client()中使用了一個結構並將其傳遞給所需的函數。 – bhakta288 2014-09-30 03:54:54