问题
I am writing a small server which creates a new thread to handle each new connection. I need to pass the socket to the function using the fourth argument of pthread_create. When trying to free the memory used for the socket i get a segfault. The communication works fine. I have tried passing a void* and also a void** (casted to void*, kind of ugly)
This is the latest cludge i'm using while trying to figure this out, later if will be doing actual work in the respond function.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <pthread.h>
void *respond(void *thread_arg)
{
void *arg = *(void**)thread_arg;
printf("responding...\n");
int client_sock;
client_sock = (int)arg;
char *message = "Write smthng to echo!\n\t";
send(client_sock,message,strlen(message),0);
char *buf = (char*)malloc(100);
int ptr = 0;
char last = ' ';
while (last != '\n') {
recv(client_sock,&last,1,0);
buf[ptr++] = last;
}
buf[ptr++] = '\n';
send(client_sock, buf, ptr, 0);
ptr = 0;
free(buf);
close(client_sock);
//free(arg); // why segfault?
//free(*(void**)thread_arg); // the same
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
int socket_desc, client_sock, addrlen, tmp;
struct sockaddr_in address;
pthread_t *responder_thread;
void *cs;
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0)
printf("could not create socket");
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
tmp = bind(socket_desc, (struct sockaddr *)&address, sizeof(address));
if (tmp < 0)
printf("could nod bind to port!");
listen(socket_desc, 5);
addrlen = sizeof(struct sockaddr_in);
while (true) {
client_sock = accept(socket_desc, (struct sockaddr *)&address, (socklen_t*)&addrlen);
if (client_sock < 0) {
printf("could not create client socket");
} else {
printf("Accepted connection!\n");
cs = malloc(sizeof(int));
cs = (void*)client_sock;
responder_thread = (pthread_t*)malloc(sizeof(pthread_t*));
tmp = pthread_create(responder_thread, NULL, respond, (void*)&cs);
//cs = NULL;
if (tmp) {
printf("pthread_create returned '%d', exiting", tmp);
exit(-1);
}
}
}
pthread_exit(NULL);
}
Lastly, to clarify; I am very inexperienced when it comes to c. :)
回答1:
try something more like this.
int* cs;
...
cs = (int*)malloc(sizeof(int));
*cs = client_sock;
...
tmp = pthread_create(responder_thread, NULL, respond, (void*)cs);
Then you don't need this casting.
void *arg = *(void**)thread_arg;
and you can just free the thread_arg.
free(thread_arg);
回答2:
You have a massive memory leak and general memory error:
cs = malloc(sizeof(int));
cs = (void*)client_sock;
The first line allocates memory and assigns the pointer to cs
, and the second line immediately throws away that pointer by overwriting it with the integral value client_sock
. Later you try to free that value, which is a flagrant error, since it's not a valid pointer.
You should structure your code like this:
int * cs = malloc(sizeof(int));
*cs = client_sock;
pthread_create(..., cs);
And the thread function:
void * respond(void * thread_arg)
{
int * cs = (int*)thread_arg;
/* ... */
free(cs);
}
There's no need for the extra indirection by taking the address of cs
.
回答3:
Don't allocate a pointer. Pass the socket file descriptor directly to pthread_create()
:
(void*)client_sock
Then, in respond()
:
client_sock = (int)thread_arg;
No malloc()
or free()
necessary.
回答4:
cs = malloc(sizeof(int));
cs = (void*)client_sock;
The second assignment makes you have a memory leak in your code.
来源:https://stackoverflow.com/questions/8719888/freeing-argument-in-function-specified-in-pthread-create