memset установка указателей символов NULL/ мусор
Ниже приведена одна функция моей программы на Си. В приведенной ниже функции я передаю 3 указателя на символы, но я совсем не использую их в функции. Однако после выполнения функции memset() значения строк становятся NULL или GARBAGE. Кто-нибудь может дать мне знать, почему это происходит?
Вот полный код.... Пожалуйста, игнорируйте плохой стиль кодирования, так как это мой тестовый код:) .
#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 ответ
Ваши указатели ip_addr
, port_no
, page
все указывают на char line[512];
которая является локальной переменной для getClientInput
функция. После возврата этой функции память освобождается.
Ваши симптомы в connect_web
происходит потому, что эта память используется для локальных переменных внутри connect_web
; поэтому изменение этих локальных переменных означает, что содержимое char line[512]
, на которые указывают ваши указатели, похоже, изменится.
Чтобы исправить это, вы можете сделать это static char line[512];
или вы могли бы иметь getClientInput
Функция динамически распределяет память для каждой строки, которую она "возвращает".
Однако ваш код уже довольно запутанный и за ним трудно следовать, поэтому неудивительно, что у вас есть ошибки памяти. Я бы порекомендовал сделать struct
содержит все необходимые вам указатели (вместо специального массива из 3 указателей или списка параметров функции) и убедитесь, что вы выделяете все для экземпляра этой структуры в одном месте. Тогда у вас может быть одна функция для освобождения всей структуры, как только вы с ней справитесь.