How to use a struct pointer returned to the in the main from a thread function? - c

I am writing a program that takes integers as command line arguments. For each of these numbers I have to create a thread which calculates Fibonacci series up to that number. That function returns a struct pointer to the main where the data is printed.
Now, I have correctly done the fib calculations and checked them by printing the series within the function.
The problem arises when I try to return the struct pointer created within the thread function and use it to print the data in the main.
typedef struct thread_func_param
{
int *fib;
int size;
} thread_func_param;
//===================================================
void *fibGen(void *parameters)
{
int num = atoi(parameters);
struct thread_func_param *p;
p = malloc (sizeof (thread_func_param));
p->size = fibSize(num);
p->fib = malloc(sizeof(int)* p->size);
//Fibonacci Calculations
//..
//.
return (void *) p;
//pthread_exit((void *) p);
}
//===================================================
int main(int argc, char* argv[])
{
void* thread_result;
thread_func_param* p = malloc( sizeof(thread_func_param));
assert(argc > 1);
int noOfThreads = argc - 1;
printf("No of Thread = %d\n", noOfThreads);
pthread_t *threadID = malloc (sizeof (pthread_t) * noOfThreads);
pthread_attr_t attributes;
pthread_attr_init(&attributes);
int i, j;
for(i = 0; i < noOfThreads; i++)
{
pthread_create(&threadID[i], &attributes, fibGen, argv[i+1]);
pthread_join(threadID[i], thread_result);
//HOW TO USE THE RETURNED DATA?
for (j = 0; j< ((thread_func_param*)thread_result->size)-1; j++)
printf(" %d ", (thread_func_param*)thread_result->fib[j]);
}
return 0;
}
The solution that I use, in the end, to print the data gives error of dereferencing a void pointer (I am new with C). How can I correct it?

Two issues here:
pthread_join() takes a void** as 2nd parameter. The code passes a void* only.
To cast a pointer wrap it into parenthesis. Here the cast
(thread_func_param*)thread_result->size
refers to size not to thread_result. So what you want is
((thread_func_param*)thread_result)->size
However a nice and clean solution would only use a void pointer interimswise. It could look like this:
int main(int argc, char* argv[])
{
thread_func_param* thread_result;
...
...
pthread_create(&threadID[i], &attributes, fibGen, argv[i+1]);
{
void * pv;
pthread_join(threadID[i], &pv);
thread_result = pv;
}
if (NULL != thread_result) /* perform some sanity checking. */
{
for (j = 0; j < thread_result->size - 1; j++)
printf(" %d ", thread_result->fib[j]);
}
...

Related

function to clear malloc, and make pointer to null

in my last question, I've asked how to use function to free an malloc'ed array, I wanted to improve my code so that the function won't just free the memory but also will set the pointer to NULL once it finishes the clearing.
Also I want a single function to do both - setting and clearing, depending on the command I'm passing, this is what I've done so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint-gcc.h>
char **set_arr(int number, char *command);
int command_read(char *command);
void clear_arr(char *arr[], int size);
char set[] = "set";
char clear[] = "clear";
int main() {
int num = // get number from user;
char** my_arr = NULL;
my_arr = set_arr(num, set);
// so far the code works as excepted
set_arr((size_t)&my_arr, clear);
return 0;
}
int command_read(char *command) {
if (strcmp(command, set) == 0)
return 'S';
if (strcmp(command, clear) == 0)
return 'C';
}
char **set_arr(int number, char *command) {
static char **arr = NULL;
static int size;
switch (command_read(command)) {
case 'S':
size = (int)number;
arr = malloc((size + 1) * sizeof(char *));
for (int i = 0; i <= size; i++) {
arr[i] = NULL;
if (i == size)
break;
arr[i] = malloc((string_len) * sizeof(char));
}
break;
case 'C':
clear_arr(arr, size);
free(arr);
uintptr_t value = number;
uint64_t *temp = (void *)value;
*temp = 0x0;
break;
}
return arr;
}
void clear_arr(char *arr[], int size) {
for (int i = 0; i < size; i++) {
free(arr[i]);
arr[i] = NULL;
}
}
I know that there is better methods to clear (and allocate memory?) but my primary question is, did I free all the memory I allocated for the array, and after the clearing, does the pointer my_arr is set correctly to NULL?
Writing a generic function to achieve your goal is not possible in Standard C because pointers to different types of objects may have a different representation so you cannot pass the address of a pointer and expect the function to handle it in a generic manner.
Yet this provision in the C Standard is not used on most current systems today. In particular, the POSIX standard mandates that all pointers have the same representation. Hence your generic function can work on these systems, with some precautions to avoid compilation warnings:
// free an array of allocated things
void free_array(void ***p, size_t count) {
void **array = *p;
for (size_t i = 0; i < count; i++) {
free(array[i]);
array[i] = NULL; // for safety
}
free(array);
*p = NULL;
}
// deal with the non portable conversion with macros
#define FREE_ARRAY(p, n) free_array((void ***)(void *)&(p), n)
// allocate an array of pointers to allocated things of size `size`.
// return a pointer to the array or `NULL` if any allocation failed
void **malloc_array(size_t count, size_t size) {
void **array = malloc(count * sizeof(*array));
if (array) {
for (size_t i = 0; i < count; i++) {
array[i] = calloc(size, 1); // allocate and initialize to all bits zero
if (array[i] == NULL) {
while (i-- > 0) {
free(array[i]);
array[i] = NULL;
}
return NULL;
}
}
}
return array;
}
#define MALLOC_ARRAY(n, type) ((type **)(void *)malloc_array(n, sizeof(type)))
#define MALLOC_2D_ARRAY(n1, n2, type) ((type **)(void *)malloc_array(n1, (n2) * sizeof(type)))
Passing the command as a string is very inefficient. You should use an int or an enum for the command, but you can use the above macros and code in your program this way:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint-gcc.h>
int main() {
int string_len = 100;
int num = 10; // get number from user;
char **my_arr = MALLOC_2D_ARRAY(num, string_len, char);
FREE_ARRAY(my_arr, num);
return 0;
}

Using an array of structures with call by reference

Here is my problem: I have to make this program for school and I spent the last hour debugging and googling and haven't found an answer.
I have an array of structures in my main and I want to give that array to my function seteverythingup (by call by reference) because in this function a string I read from a file is split up, and I want to write it into the structure but I always get a SIGSEV error when strcpy with the struct array.
This is my main:
int main(int argc, char *argv[])
{
FILE* datei;
int size = 10;
int used = 0;
char line[1000];
struct raeume *arr = (raeume *) malloc(size * sizeof(raeume*));
if(arr == NULL){
return 0;
}
if(argc < 2){
return 0;
}
datei = fopen(argv[1], "rt");
if(datei == NULL){
return 0;
}
fgets(line,sizeof(line),datei);
while(fgets(line,sizeof(line),datei)){
int l = strlen(line);
if(line[l-1] == '\n'){
line[l-1] = '\0';
}
seteverythingup(&line,arr,size,&used);
}
ausgabeunsortiert(arr,size);
fclose(datei);
return 0;
}
and this is my function:
void seteverythingup(char line[],struct raeume *arr[], int size,int used)
{
char *token,raumnummer[5],klasse[6];
int tische = 0;
const char c[2] = ";";
int i=0;
token = strtok(line, c);
strcpy(raumnummer,token);
while(token != NULL )
{
token = strtok(NULL, c);
if(i==0){
strcpy(klasse,token);
}else if(i==1){
sscanf(token,"%d",&tische);
}
i++;
}
managesize(&arr[size],&size,used);
strcpy(arr[used]->number,raumnummer);
strcpy(arr[used]->klasse,klasse);
arr[used]->tische = tische;
used++;
}
Edit: Since there is more confusion I wrote a short program that works out the part you are having trouble with.
#include <cstdlib>
struct raeume {
int foo;
int bar;
};
void seteverythingup(struct raeume *arr, size_t len) {
for (size_t i = 0; i < len; ++i) {
arr[i].foo = 42;
arr[i].bar = 53;
}
}
int main() {
const size_t size = 10;
struct raeume *arr = (struct raeume*) malloc(size * sizeof(struct raeume));
seteverythingup(arr, size);
return 0;
}
So basically the signature of your functions is somewhat odd. Malloc returns you a pointer to a memory location. So you really dont need a pointer to an array. Just pass the function the pointer you got from malloc and the function will be able to manipulate that region.
Original Answer:
malloc(size * sizeof(raeume*));
This is probably the part of the code that gives you a hard time. sizeof returns the size of a type. You ask sizeof how many bytes a pointer to you raeume struct requires. what you probably wanted to do is ask for the size of the struct itself and allocate size times space for that. So the correct call to malloc would be:
malloc(size * sizeof(struct raeume));

Segmentation fault 11 thread program

I'm having the error "Segmentation fault 11" with the following code :
I created a thread who give in parameters a struct.
I think the problem is in the declaration of the function *MARIT.
Sorry for my bad English I am French.
struct parametres {
double *T;
int N; //taille
};
void *MARIT(struct parametres parametres)
{
int *somme =0;
float *moyenne = 0;
int i;
for(i = 0; i < parametres.N; i++)
*somme = *somme + parametres.T[i];
printf("somme : %d",somme);
*moyenne = (*somme/(parametres.N+0.0));
pthread_exit(moyenne);
}`
int main(int argc, char* argv[])
{
float temps;
clock_t t1, t2;
t1 = clock();
struct parametres params;
printf("Salut à toi !\n");
printf("Donnez la taille du tableau :" );
scanf("%d", &params.N);
params.T = malloc( params.N * sizeof(double) );
int i = 0;
int nombre_aleatoire = 0;
for(i=0; i<params.N; i++){
nombre_aleatoire =  (rand() % 1000) + 1;
params.T[i]=nombre_aleatoire;
}
pthread_t arith,quadrat,cubi;
if(pthread_create(&arith, NULL, MARIT, (void*)&params) != 0)
{
perror("pthread_create");
exit(1);
}
double *result=0;
pthread_join(arith, (void**)&result);
printf("le resultat du thread : %f",result);
return 0;
}
I don't know what's the problem.
There are a couple of problems with your code.
First, the signature of MARIT. It must take a sinlge void* parameter.
Second, somme and moyenne are declared as pointers, but you don't allocate any memory for them. This is what is causing the segfault.
Third, the return value must be a void pointer. That means that it must have the size of a pointer and the value it points to must persist past the call (returning the address of an automatic variable inside MARIT is not ok).
Fourth, main expects a double to be returned, so change the type of moyenne.
Fixing all three issues could be done like this:
void *MARIT(void *param)
{
struct parametres *parametres = (struct parametres*)param;
int somme =0;
double moyenne = 0, *ret;
int i;
for(i = 0; i < parametres->N; i++)
somme = somme + parametres->T[i];
printf("somme : %d",somme);
moyenne = (somme/(parametres->N+0.0));
ret = malloc(sizeof ret);
*ret = moyenne;
pthread_exit(ret);
}
Note that, when the main function is done processing the retrun value it should free it. In this case, where the program ends right afterwards, freeing the memory is not really necessary.
You also need to change the printf in main:
printf("le resultat du thread : %f", *result);
int *somme =0;
...
*somme = ... // segmentation fault here
because you declared somme as a pointer (a NULL pointer moreover), to a non-allocated memory. Solution: int somme = 0;
Same goes to the varible moyenne : float moyenne = 0;
> SYNOPSIS
> #include <pthread.h>
>
> int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
> void *(*start_routine) (void *), void *arg);
your function must have a signature like
void * start_routine (void *);
the moment that is wrong almost everything is undefined behavior.
and you must always allocate memory to a pointer before doing operations on space they are pointing to *somme and *moyenne are crashing for same reason. Though I am complete unaware of your choice of using pointers instead of normal variables.
void *MARIT(void *arg) // change <--here
{
struct parametres *parametres = (struct parametres *) arg; // change <--here
int *somme = malloc(sizeof(int)); // change <-- here
float *moyenne = malloc(sizeof(float)); // change <-- here
int i;
for(i = 0; i < parametres->N; i++) // change <--here
*somme = *somme + parametres->T[i]; // change <--here
printf("somme : %d",somme);
*moyenne = (*somme/(parametres->N+0.0)); // change <--here
pthread_exit(moyenne);
}`

Setting a double pointer array

I know there are a lot of double pointer questions, but I couldn't find one that pertained to starting an array.
In the code below, I can set pointers in main by ptrs[0] = &array[0];, but the code halts when enqueue() calls *queue[i] = p;. Why is that? I don't know if it matters, but ptrs[] is not initialized.
#define QUEUE_LEN 5
int *ptrs[5];
int array[5] = {1,2,3,4,5};
void enqueue(int *p, int **queue) {
int i = 0;
int *tmp;
// Find correct slot
while (*queue && *queue[i] >= *p) {
i++;
}
// Error no free slots
if (i == QUEUE_LEN) {
printf("No free slots.\r\n");
return;
}
// Insert process
if (!*queue) {
*queue[i] = p;
return;
}
else {
tmp = *queue[i];
*queue[i] = p;
}
// Increment the other processes
return;
}
int main(int argc, char** argv) {
int i;
for (i=0; i<5; i++) {
enqueue(&array[i], ptrs);
}
for (i=0; i<QUEUE_LEN; i++)
printf("%d\n", *(ptrs[i]));
return 0;
}
After first loop, i will remain zero. Here:
if (!*queue) {
*queue[i] = p;
return;
}
You check, that *queue is 0 and dereference it as well. It is UB.
PS. Btw, this:
*queue[i] = p;
Will not compiles, since *queue[i] has type int, but p has type int*.
// Find correct slot
while (*queue && *queue[i] >= *p) {
i++;
}
This will access some random memory address taken from uninitialized ptrs value.
Your check for *queue != 0 is not enough, you need to initialize array with zeores as:
int *ptrs[5] = {0};
And you still need to allocate memory you are attempting to write later when inserting.

attempt to free memory causes error

I have declared the following struct:
typedef struct _RECOGNITIONRESULT {
int begin_time_ms, end_time_ms;
char* word;
} RECOGNITIONRESULT;
There is a method that creates an array of RECOGNITIONRESULT and fills it (for test purposes only):
void test_realloc(RECOGNITIONRESULT** p, int count){
int i;
*p = (RECOGNITIONRESULT *)realloc(*p, count * sizeof(RECOGNITIONRESULT));
for (i = 0; i < count; i++){
(*p)[i].begin_time_ms = 2*i;
(*p)[i].end_time_ms = 2*i+1;
(*p)[i].word=(char *) malloc ( (strlen("hello"+1) * sizeof(char ) ));
strcpy((*p)[i].word,"hello");
}
}
The method to free memory is:
void free_realloc(RECOGNITIONRESULT* p, int count){
int i = 0;
if(p != NULL){
if (count > 0){
for (i = 0; i < count; i++){
free(p[i].word); //THE PROBLEM IS HERE.
}
}
free(p);
}
}
The main method calls those methods like this:
int main(int argc, char** argv)
{
int count = 10;
RECOGNITIONRESULT *p = NULL;
test_realloc(&p,count);
free_realloc(p,count);
return 0;
}
Then if I try to free the memory allocated for "word", I get the following error:
HEAP CORRUPTION DETECTED: after normal block (#63) at 0x003D31D8.
CRT detected that the application wrote to memory after end of heap buffer.
Using the debugger I've discovered that the crash occurs when calling free(p[i].word);
What am I doing wrong? How can I free he memory for the strings?
The problem is in your allocation of memory for word. strlen("hello"+1) should be strlen("hello")+1.
Since you appear to allocate a whole array of structures in one strike
RECOGNITIONRESULT **p;
*p = (RECOGNITIONRESULT *)realloc(*p, count * sizeof(RECOGNITIONRESULT));
you can free them in one call to free() as well :
void free_realloc(RECOGNITIONRESULT *p, int count){
free(p);
}
And the strlen("hello"+1) is also wrong, as detected by Chowlett.

Resources