I have tried to follow the procedures of several answers/tuturials and I'm still getting segmentation fault on passing multiple arguments to a thread? What am I doing wrong?
struct:
struct client_struct {
int socketId;
char *message;
};
process function:
// Handle socket session
void *process(void *client)
{
client_struct *tmpClient = (client_struct*)client;
char sendline[BUFFSIZE], recvline[BUFFSIZE];
printf("can't reach this: %i\n", tmpClient->socketId);
strncpy(sendline, tmpClient->message, sizeof(sendline)-1);
sendline[sizeof(sendline)-1] = '\0';
}
called from main:
int sendMessage(const char *message, int sock)
{
int result;
pthread_t process_thread;
struct client_struct * client;
client->socketId = sock;
strcpy(client->message, message);
printf("segmentation fault here: %s\n", client->message);
pthread_create(&process_thread, NULL, process, client);
pthread_detach(process_thread);
}
Classic problem with undefined behavior when pointer is not initialized.
struct client_struct * client;
client = malloc(sizeof(*client)); //Allocate memory for client
client->... = ...; //DO you job
By doing struct client_struct * client; you are only declaring variable which will (probably at some point) point to data of type struct client_struct. Since you don't have your data yet, dereferencing non-initialized pointer leads to undefined behavior.
By using malloc, you are setting up valid data for your pointer.
A simple proxyargs struct can be used also:
struct Args
{ int a; float f; char msg[10]; };
...
static void* callback(void* userData)
{
Args* a = (Args*) userData;
/* use args here */
}
...
Args mArgs = {10, 2.0, "message"};
pthread_create(&thread,NULL, callback, (Args*)&mArgs);
enter code here
Related
I'm confused about how I define a struct function in a source file or in the struct itself. Yes I have read a similar Stack Overflow question, but that asks if you can define a function declared in the struct itself. Basically in simple matters, I have this "NetworkDriver" struct:
typedef struct
{
char *name;
bool initialized;
int32_t status;
int (*initialize)(void);
} NetworkDriver;
As you can see, I'm trying to define the function pointer that has been initialized in the struct. How do we go about doing this?
The question being tagged as C (not C++) it should be noted that there is no such thing as a struct function in C. In the given code snippet, initialize is simply a data member of the struct typedef'd as NetworkDriver declared to be a pointer to a function that takes no arguments and returns an int.
The mechanics of defining and using the variable are the same as for any function pointer: it must be set to point to a function with the given prototype, then it can be called with the usual function syntax.
#include <stdio.h>
typedef struct
{
int (*initialize)(void);
} NetworkDriver;
int init(void)
{
printf("initializing...\n");
return 0;
}
int main(void)
{
NetworkDriver nd;
nd.initialize = init;
nd.initialize(); // prints 'initializing...'
return 0;
}
Not sure if I get the problem; what you did in your code fragment was declaring a type. There is no instance of this type yet that you could initialize; you need to declare an instance; either by adding it to the line at the end: }NetworkDriver var;, or by adding another line afterwards: NetworkDriver var;.
Either way, you can initialize this instance by adding ={"whatever",true,0,&function} to it; or specifically only that function pointer by adding a further line var.initialize = &funciton;.
Below is what I could get closest to what you are telling. I made some change (used int instead of bool), and also added one more function pointer in your NetworkDriver structure, and added parameters to the functions.
However, it seems you want each instance of NetworkDriver have its own initialize function. But what I have done is I have defined the initialize function once, and each instance of NetworkDriver have a pointer to it. Not exactly like what you are saying, but this is what I could think of.
As dxib has mentioned in his answer, the functions will still have to be explicitly called. I is not something like a constructor in C++. Also before calling, these functin pointers inside the structure have to be assigned the address of functions explicitly.
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define NO_ERR 10
#define NAME_ERR 11
#define INITIALIZED_ERR 12
typedef struct
{
char *name;
int initialized;
int32_t status;
int (*initialize)(void *, char *);
void (*disp_info)(void *); /* Note: one more func pointer */
}NetworkDriver;
/* Function prototype declarations */
int nd_init(void *ndr, char *name);
void nd_disp_info(void *ndr);
/* main: test NetworkDriver and nd_init */
int main(void)
{
NetworkDriver nd;
nd.initialized = FALSE;
nd.initialize = nd_init;
nd.disp_info = nd_disp_info;
if (nd.initialize(&nd, "foo")) { /* Initialize driver */
printf("Error: Initialization error\n");
exit(1);
}
nd.disp_info(&nd); /* display nd's info */
/* nd_init: initialize a NetworkDriver */
int nd_init(void *ndr, char *name)
{
NetworkDriver *nd;
nd = (NetworkDriver *) ndr;
if (!(nd->name = name)) {
nd->status = NAME_ERR;
return 1;
}
if (nd->initialized != TRUE) {
if (!(nd->initialized = TRUE)) {
nd->status = INITIALIZED_ERR;
return 1;
}
}
/* Successfully initialized */
nd->status = NO_ERR;
return 0;
}
/* nd_disp_info: display NetworkDriver info */
void nd_disp_info(void *ndr)
{
NetworkDriver *nd;
nd = (NetworkDriver *) ndr;
/* If this driver was not initialized without err */
if (nd->status != NO_ERR) {
printf("NetworkDriver was not initialized correctly\n");
return;
}
/* Print info */
printf("=== NetworkDriver info ===\n");
printf("Name: %s\n", nd->name);
printf("Initialized ? %s\n", nd->initialized == TRUE ? "TRUE" :
"FALSE");
printf("Status: %d\n", (int) nd->status);
}
After some research I didn't find a good way to implement the std::bind in C.
I build a small program that implements an equivalent of std::bind in C by hacking the stack.
There's two functions I will try to bind to function with pre-defined arguments.
My problem is this code is only working under Windows. Under Linux, this is a mess. I this the problem is my knowledge of the stack and the way that arguments are store in memory.
Thanks,
Please, find below the code I made:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
The two functions I want to bind :
void test1 (int nombre, char t, int nombre2)
{
printf ("test 1 : %d%c%d\n", nombre, t, nombre2);
}
void test2 (char t, int nombre, int nombre2)
{
printf ("test 2 : %c%d%d\n", t, nombre, nombre2);
}
Two struct that will store the argument of each function (order of fields is important).
typedef struct {
int nombre;
char t;
int nombre2;
} struct1;
typedef struct {
char t;
int nombre;
int nombre2;
} struct2;
This "fake" struct will be use to write on the stack by dereferencing a structvoid* variable.
// Size must be bigger than every struct*
typedef struct {
int i[10];
} structvoid;
The main function.
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
void *func2 = (void *)&test2;
void (*functionPtrc)(structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
void *datac = malloc (sizeof (structvoid));
memcpy(datac, &data1, sizeof (struct1));
data[0] = (structvoid*)datac;
functions[0] = func1;
// Same thing with function 2.
struct2 data2;
data2.t = 'a';
data2.nombre = 5;
data2.nombre2 = 10;
datac = malloc (sizeof (structvoid));
memcpy(datac, &data2, sizeof (struct2));
data[1] = (structvoid*)datac;
functions[1] = func2;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// All the hack is here. By dereferencing the data, this will write on the stack all arguments need by the test1 function.
functionPtrc(*data[0]);
functionPtrc = functions[1];
functionPtrc(*data[1]);
// To check the result.
test1 (data1.nombre, data1.t, data1.nombre2);
test2 (data2.t, data2.nombre, data2.nombre2);
return 0;
}
EDIT
Here a new version of the program by calling function via the calling convention. I only wrote the new lines. The problem of this method is I can only store data inside a "void *" field. If I increase the size of structvoid, I got garbage behaviors.
// Structure that memories each argument
typedef struct {
void *i[1];
} structvoid;
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
// Let's start with a maximum of 5 arguments
void (*functionPtrc)(structurevoid, structurevoid, structurevoid, structurevoid, structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
structvoid *datac = malloc (sizeof (structvoid)*5);
memcpy(&datac[0], &data1.nombre, sizeof (data1.nombre));
memcpy(&datac[1], &data1.t, sizeof (data1.t));
memcpy(&datac[2], &data1.nombre2, sizeof (data1.nombre2));
data[0] = datac;
functions[0] = func1;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// Call the function with the arguments. The unused argument will be ignored.
functionPtrc(data[0][0], data[0][1], data[0][2], data[0][3], data[0][4]);
}
Can I pass two structures as parameters to a pthread in a C program. I need to do something like this:
void *funtion1(void *pass_arg, void *pass_arg1)
{
struct thread_arg *con = pass_arg;
struct thread_arg1 *con = pass_arg1;
//necessary code
}
int main()
{
pthread_t threaad;
//necessary code
while(1)
{
th1 = pthread_create(&threaad, NULL, function1, (void *)&pass_arg, (void*)&pass_arg);
//necessary codes
}
pthread_exit(NULL);
return 1;
}
I mean is there any way I can pass two structures into the same function while using pthread? Operating Platform: Linux.
Not directly, because the functions in libpthread accept only one user data argument. But that should be enough, shouldn't it?
struct user_struct {
void *p1, *p2;
} arg = { &arg1, &arg2 };
pthread_create(&tid, NULL, threadfunc, &arg);
Also, don't cast pointers to void *, it's superfluous, dangerous and decreases readability.
Define a new struct type which contains the two original types as members. Call it something meaningful like thread_args.
I solved the problem by nesting the two structures into a single structure like this:
struct s1
{
//variables
};
struct s2
{
//variables
}
struct s3
{
struct s1 ss1;
struct s2 ss2;
}
void *funtion1(void *pass_arg)
{
struct s3 *con = pass_arg;
//necessary code
}
int main()
{
//code
th1 = pthread_create(&thread, NULL, function1, (void *)&pass_arg);
}
when i create a thread, i want to pass several arguments.
So i define in a header file the following:
struct data{
char *palabra;
char *directorio;
FILE *fd;
DIR *diro;
struct dirent *strdir;
};
In a .c file i do the following
if (pthread_create ( &thread_id[i], NULL, &hilos_hijos, ??? ) != 0){
perror("Error al crear el hilo. \n");
exit(EXIT_FAILURE);
}
How do i pass all this arguments to the threads. I though about:
1) first use malloc to allocate memory for this structure and then give each parameter a value:
struct data *info
info = malloc(sizeof(struct data));
info->palabra = ...;
2) define
struct data info
info.palabra = ... ;
info.directorio = ...;
and then, how do i access these parameters in the thread
void thread_function ( void *arguments){
???
}
thanks in advance
Here is a working (and relatively small) example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/*
* To compile:
* cc thread.c -o thread-test -lpthread
*/
struct info {
char first_name[64];
char last_name[64];
};
void *thread_worker(void *data)
{
int i;
struct info *info = data;
for (i = 0; i < 100; i++) {
printf("Hello, %s %s!\n", info->first_name, info->last_name);
}
}
int main(int argc, char **argv)
{
pthread_t thread_id;
struct info *info = malloc(sizeof(struct info));
strcpy(info->first_name, "Sean");
strcpy(info->last_name, "Bright");
if (pthread_create(&thread_id, NULL, thread_worker, info)) {
fprintf(stderr, "No threads for you.\n");
return 1;
}
pthread_join(thread_id, NULL);
return 0;
}
Do not use option #2. The data structure could be overwritten (explicitly, for instance using the same structure to start another thread, or implicitly, for instance having it overwritten on the stack). Use option #1.
To get at your data, at the start of your thread, do
struct data *info = (struct data*)arguments;
Then access info as normal. Make sure to free it when the thread is done (or, as I prefer, have the caller free it after joining with the thread).
Create a pointer to a struct like you do in the first case above:
//create a pointer to a struct of type data and allocate memory to it
struct data *info
info = malloc(sizeof(struct data));
//set its fields
info->palabra = ...;
info->directoro = ...;
//call pthread_create casting the struct to a `void *`
pthread_create ( &thread_id[i], NULL, &hilos_hijos, (void *)data);
1) you need to use malloc and not define like below
struct data *info;
info = (struct data *)malloc(sizeof(struct data));
and pass the pointer of the structure in ptherad call as below
pthread_create ( &thread_id[i], NULL, &thread_fn, (void *)info );
2) you can access them in thread function as below
void thread_function ( void *arguments){
struct data *info = (struct data *)arguments;
info->....
}
Which way is best to get S to a GSourceFunc? Or neither?
typedef struct{
//...
}S;
struct MS{
//..
S *St;
};
static gboolean AL_Calback(gpointer data){
S *St = (S*)user_data;
St->Something = SomethingElse;
return TRUE;
}
int main (int argc, char *argv[]){
//...
MS *MainStruct = gnew0(MS, 1);
Mainstruct->St = gnew0(S, 1);
clutter_threads_add_timeout_full(G_PRIORITY_HIGH, 100, AL_Callback, MainStruct->St, NULL);
//...
}
or like this,
typedef struct{
//...
}S;
struct MS{
//..
S St;
};
static gboolean AL_Calback(gpointer data){
MS *MV = (MS*)user_data;
MV->S.something = SomethingElse;
return TRUE;
}
int main (int argc, char *argv[]){
//...
MS *MainStruct = gnew0(MS, 1);
clutter_threads_add_timeout_full(G_PRIORITY_HIGH, 100, AL_Callback, MainStruct, NULL);
//...
}
I've tried other ways, but have not been able to make them work. clutter_add_timeout needs to take a pointer as an argument.
If you are passing the parameter to clutter_threads_add_timeout_Full via pointer, then you could just pass the address of the St member of MainStruct thus reducing the need for dynamic allocation (for the inner structure).
struct MainStruct{
//..
S St; // note: no pointer
};
// in main
MainStruct* ms = gnew0(MS, 1);
clutter_threads_add_timeout_Full(G_PRIORITY_HIGH, 100, AL_Callback, &(ms->St),
NULL);
Edit: updated code to dynamically allocate MainStruct structure to avoid possible segfault as pointed out by ptomato