I'm getting a seg fault within this code, but I can't find the problem anywhere. It compiles just fine with -lpthread, but it just won't run. This program takes in an integer from the command line and then creates a new thread to calculate the collatz conjecture using that value. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void print_con();
void calc_con(int *n);
int * values[1000];
int main(int argc, char * argv[])
{
int* num;
*num = 15;
pthread_t thread;
pthread_create(&thread,(pthread_attr_t*)NULL, (void *)&calc_con, (void *)num);
pthread_join(thread, NULL);
print_con();
return 0;
}
void calc_con(int *n)
{
int i = 0;
int * x;
*x = *n;
*values[0] = *x;
while(*x > 1)
{
if(*x % 2 == 0)
*x /= 2;
else if(*x % 2 == 1)
{
*x *= 3;
*x++;
}
i++;
*values[i] = *x;
}
pthread_exit(0);
}
void print_con()
{
int i;
for(i = 0; i < 1000; i++)
{
if(*values[i] > 0)
printf("%d", *values[i]);
}
}
okay you need to pass a void * as an argument to pthread_create, but you still need to respect the basics:
int* num;
*num = 15;
pthread_t thread;
pthread_create(&thread,(pthread_attr_t*)NULL, (void *)&calc_con, (void *)num);
Here *num = 15; you're writing 15 to an uninitialized pointer. That's undefined behaviour.
I would do:
int num = 15;
pthread_t thread;
pthread_create(&thread,(pthread_attr_t*)NULL, &calc_con, &num);
note that you don't have to cast to void * from pointers on non-void. Since num is declared in the main routine, you can pass a pointer on it to your threads safely.
note that as pointed by dasblinkenlight, you also have to fix the recieving end, in calc_con, which has the same issue:
int * x; // uninitialized pointer
*x = *n; // copy data "in the woods"
just dereference into a local variable and you have your value:
int x = *((int *)n);
and another one:
int * values[1000];
is an uninitialized array of integer pointers, not an array of integers like you're intending. It should be
int values[1000];
then
values[0] = x;
(it's not because there's a lot of * operators that it's good code)
You are passing an int to your thread using a void*. This will work on many platforms, but there is no guarantees that the number would "round-trip" correctly. Once you get pointer back, you save it in a dereferenced uninitialized pointer, which is incorrect.
Pass a pointer to num instead, and copy the pointer into x directly:
void calc_con(void *n);
...
void calc_con(void *n) {
int i = 0;
int * x = n;
*values[0] = *x;
while(*x > 1) {
if(*x % 2 == 0) {
*x /= 2;
} else if(*x % 2 == 1) {
*x *= 3;
*x++;
}
i++;
*values[i] = *x;
}
pthread_exit(0);
}
...
int num = 15;
pthread_create(&thread,(pthread_attr_t*)NULL, calc_con, (void *)&num);
Related
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X** a, int size){
for (int i = 0;i < size; i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container = (struct X*)malloc(sizeof(struct X) * n);
read_record(&container, n);
}
I created a 1D array of size n, then I passed it by reference to the function read_record. However, when I execute the program, there is a segmentation fault. What is the problem?
EDIT:
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. That's why I want to send the array as a reference. If I did it in main then I would write:
container = realloc(container, (n + 10) * sizeof(Struct X));
How can I do this in the function?
container is already a pointer, you don't need to pass the address-of the pointer, instead:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X *a, size_t size)
{
for (size_t i = 0; i < size; i++) {
a[i].deg = 0;
}
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
read_record(container, n);
}
also, prefer size_t to store the number of allocated objects.
Nitpick: read_record doesn't seem a good name for a function that modifies the contents of the records.
EDIT: As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
Same approach but returning a reallocated container:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
struct X *read_record(struct X *a, size_t size)
{
struct X *new = realloc(a, sizeof(struct X) * size);
if (new != NULL)
{
for (size_t i = 0; i < size; i++) {
new[i].deg = 0;
}
}
return new;
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
container = read_record(container, n * 2);
if (container == NULL)
{
fprintf(stderr, "Can't read record\n");
exit(EXIT_FAILURE);
}
}
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
The pointer is passed by value, so to save the changes and have them usable outside the function scope, after the function ends, i.e. in main, a pointer to pointer must be the argument, and the address of the pointer must be passed, your overall assessment is correct.
Your implementation, however, is not correct, here's how you shoud do it:
Live demo
void read_record(struct X **a, int size) //double pointer
{
*a = realloc(*a, sizeof **a * (size + 10)); //reallocate memory for 20 ints
if (*a == NULL)
{
perror("malloc");
}
for (int i = 0; i < size + 10; i++) //assing new values
{
(*a)[i].deg = 1;
}
}
int main()
{
int n = 10;
struct X *container = malloc(sizeof *container * n); //original allocation
//the pointer now has space for 10 ints
if (container == NULL)
{ //check allocation errors
perror("malloc");
}
for (int i = 0; i < n; i++) //assign values
{
container[i].deg = 0;
}
read_record(&container, n); //pass by reference
//the pointer now has space for 20 ints
}
Alternatively you can return the pointer instead, refering to David Ranieri's answer.
The first function parameter has the pointer to pointer type struct X**. So dereferencing the parameter a you will get a pointer of the type struct X*. Now you may apply the subscript operator that yields lvalue of the type struct X..
That is the function definition will look like
void read_record(struct X** a,int size){
for (int i=0;i<size;i++){
( *a )[i].deg = 0;
}
}
Or this statement
( *a )[i].deg = 0;
may be substituted for this statement
a[0][i].deg = 0;
On the other hand, there is no great sense to declare the first parameter as having the type struct X**. The function can look simpler as for example
void read_record(struct X* a,int size){
for (int i=0;i<size;i++){
a[i].deg = 0;
}
}
and be called like
read_record( container, n );
When you call read_record you pass a pointer to a pointer to the first element of an array of X structures.
But inside the read_record you treat it as a pointer to the first element of an array of pointers to X structures (i.e. as an array of pointers to X). There's a subtle but very important difference here.
If you want to emulate pass-by-reference for the pointer variable, you need to dereference it inside the read_record to get the original pointer (and remember that then you have an array of objects, not pointers):
(*a)[i].deg = 0;
Double pointer is the problem. The code should be:
void read_record(struct X* a,int size){ // Check the change
for (int i=0;i<size;i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container=(struct X*)malloc(sizeof(struct X)*n);
read_record(container,n); // Check the change
}
I've been trying to get an array of ints back from a thread. I think I'm really close. The errors I'm getting are about dereferencing a void pointer and invalid use of a void expression here
assn3.c:29:29: error: dereferencing ‘void *’ pointer [-Werror]
printf(" %d", (int)answer[j]);
^
assn3.c:29:18: error: invalid use of void expression
printf(" %d", (int)answer[j]);
I've tried changing the return type of my functions to int* but it didn't seem to like that. What am I missing here?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *getFactors(void *param);
int main(int argc, char *argv[])
{
for(int i = argc; i > 0; i--)
{
void *answer;
pthread_t tid;
pthread_attr_t attr;
if (atoi(argv[i])<0)
{
fprintf(stderr, "%d must be > 0\n", atoi(argv[i]));
return -1;
}
pthread_attr_init(&attr);
pthread_create(&tid, &attr, getFactors, argv[i]);
pthread_join(tid, &answer);
printf("%d", atoi(argv[i]));
printf(":");
for(int j = 0; j < sizeof(answer); j++)
{
printf(" %d", (int)answer[j]);
}
printf("\n");
}
}
And the thread function
void *getFactors(void *param)
{
int a[10];
int n = atoi(param);
int i = 0;
while (n%2 == 0)
{
a[i] = 2;
n/=2;
i++;
}
int f=3;
while (f * f <= n)
{
if (n % f == 0)
{
a[i]=f;
n /= f;
i++;
}
else
{
f += 2;
}
}
if (n<1)
{
a[i]=n;
i++;
}
int* buffer = (int*) malloc(i);
buffer = a;
return (void *) buffer;
pthread_exit(0);
}
void *answer;
...
int * answer_beeing_an_int_arr = answer;
printf(" %d", answer_beeing_an_int_arr[j]);
This is what you want. But you find that:
printf(" %d", (int)answer[j]);
does not work. Why you ask? It's because the cast (int) has lower precedence than the array subscript [j], and also you don't tell the compiler that answer is a pointer to ints, only that it should first get the value, then cast to int. You want this:
printf(" %d", ((int*)answer)[j]);
You want to tell the compiler, that the answer is a pointer to int. Then you want to add to that that pointer sizeof(int) * j bytes and dereference it.
And remember to free(answer).
Now to your code:
buffer = a;
is wrong. It assigns the pointer to another pointer. You want to copy the values behind the pointers, not pointers themselves. You need:
memcpy(buffer, a, sizeof(int) * i);
or
for (size_t j = 0; j < i; ++j) {
buffer[j] = a[j];
}
to copy array values.
... = malloc(i);
This will allocate i bytes. An int does not have 1 byte (CHAR_BIT bits, probably 8). It has more. It can be 2, can be more. sizeof(int) will tell you how many bytes an int has. So it has to be:
int *buffer = malloc(i * sizeof(int));
or as I like it:
int *buffer = malloc(i * sizeof(*buffer));
Also:
int* buffer = (int*) malloc(i);
...
return (void *) buffer;
No need to cast a pointer to void* and from void*. void* is a generic pointer, it's a pointer to nothing. Just:
int* buffer = malloc(i * sizeof(*buffer));
...
return buffer;
There are several things wrong here:
for(int j = 0; j < sizeof(answer); j++) // This will NOT tell you the #/elements in the array
pthread_join() is probably not the best way to pass back your integer buffer
And, of course, printf(" %d", (int)answer[j]); is a compile error :(
SUGGESTION:
Read through this tutorial, and restructure your code accordingly:
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
Or you can scan through this:
http://www.cs.kent.edu/~ruttan/sysprog/lectures/multi-thread/multi-thread.html
There are a few things you need to correct as pointed earlier.
As pointed, do not use a local variable as a return address. It will not be accessible when the thread returns. It is better to use a global variable and allocate memory dynamically. You can free it in the function which has created the thread.
For accessing variables which are changed by a thread, you can either pass it to the thread function using the fourth argument in pthread_create(3) and later access it. Or access it using pthread_join as a return value.
Might need to use a mutex or other synchronization primitives if multiple threads are accessing the variable.
One simple example of returning an array using pthread_join(3) is given below.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#define ARRAY_LEN 10
void *functionPthread(void *);
int *retArray;
int main()
{
int rc, i;
pthread_t th;
retArray = (int*) malloc(sizeof(int) *ARRAY_LEN);
if(rc = pthread_create(&th, NULL, &functionPthread, NULL))
{
printf("Thread creation failed, return code %d, errno %d", rc, errno);
}
pthread_join(th, (void**)&retArray);
for(i = 0; i < ARRAY_LEN; i++)
printf("%d ", retArray[i]);
printf("\n");
free(retArray);
return 0;
}
void *functionPthread(void *)
{
int i;
for(i = 0; i < ARRAY_LEN; i++)
retArray[i] = i;
return retArray;
}
I am having a trouble while practicing double pointer
The Error is "EXE_BAD_ACCESS" in Xcode
#include <stdio.h>
/* Program to Get Min and Max Value
in Array */
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
**maxPtr=arr[0]; // Error Line
**minPtr=arr[0]; // Error Line
for(i=1; i<5; i++)
{
if(arr[i]>**maxPtr)
**maxPtr=arr[i];
else if(arr[i]<**minPtr)
**minPtr=arr[i];
}
}
int main()
{
int arr[5]={4, 5, 7, 2, 6};
int *maxptr;
int *minptr;
SaveValue(&maxptr, &minptr, arr);
printf("%d, %d \n", *maxptr, *minptr);
}
I've thought that *dptr of **dptr = &ptr is *ptr
and **dptr means variable which *ptr pointing.
so I assume that **dptr = arr[0] means save first num of arr by reference at variable which *ptr pointing!
but I experiencing access error now.. I will thank for your help!
void SaveValue(int **maxPtr, int **minPtr, int arr[]); provides pointers to pointers to int so use them as such.
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr=arr + 0; /* same as *maxPtr = &arr[0]; */
*minPtr=arr + 0; /* same as *maxPtr = &arr[0]; */
for(i = 1; i < 5; i++)
{
if(arr[i] > **maxPtr)
*maxPtr = arr + i; /* same as *maxPtr = &arr[i]; */
else if(arr[i] < **minPtr)
*minPtr = arr + i; /* same as *minPtr = &arr[i]; */
}
}
Also this interface is a bit dangerous and unflexible; so why not pass the size of the array as well:
void SaveValue(int **maxPtr, int **minPtr, int arr[], ssize_t s)
{
*maxPtr=arr + 0;
*minPtr=arr + 0;
for(--s; s >= 0; --s)
{
if(arr[s] > **maxPtr)
{
*maxPtr = arr + s;
}
else if(arr[i] < **minPtr)
{
*minPtr = arr + s;
}
}
}
Call the fcuntion like this:
SaveValue(&maxptr, &minptr, arr, sizeof arr/sizeof *arr);
As the return value of the function is unused we could utlize it to apply some error inidication to allow the user of the function to write more stable code:
int SaveValue(int ** maxPtr, int ** minPtr, int arr[], ssize_t s)
{
int result = 0;
if ((NULL == arr) || (NULL == maxPtr) || (NULL == minPtr) || (0 > s))
{
result = -1;
errno = EINVAL;
}
else
{
*maxPtr=arr + 0;
*minPtr=arr + 0;
for(--s; s >= 0; --s)
{
if(arr[s] > **maxPtr)
{
*maxPtr = arr + s;
}
else if(arr[i] < **minPtr)
{
*minPtr = arr + s;
}
}
}
return result;
}
Use it like this:
#include <stdio.h>
int SaveValue(int ** maxPtr, int ** minPtr, int arr[], ssize_t s);
int main(void)
{
int arr[5]={4, 5, 7, 2, 6};
int *maxPtr;
int *minPtr;
int result = SaveValue(&maxPtr, &minPtr, arr, sizeof arr/sizeof *arr);
if (-1 == result)
{
perror("SaveValue() failed")
}
else
{
printf("%d, %d \n", *maxPtr, *minPtr);
}
}
The pointer should be pointing to valid memory location before dereferencing it else it will lead to undefined behavior. Below changes will fix your error.
int max;
int min;
int *maxptr = &max;
int *minptr = &min;
There is no need of double pointer here change your function prototype to
void SaveValue(int *maxPtr, int *minPtr, int arr[])
Have
int max;
int min;
in main() and call this API accordingly
SaveValue(&max,&min,arr);
I'll assume your code is purely for pointer learning purposes and not an attempt to implement this operation in a practical situation. So if you want to have maxptr and minptr in main() pointing to the maximum and minimum values in arr[], I think you should change your double pointer assignments from **maxPtr=arr[0] to *maxPtr=&arr[0], so your code would become:
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr = &arr[0]; // Error Line
*minPtr = &arr[0]; // Error Line
for (i = 1; i < 5; i++) {
if (arr[i] > **maxPtr)
*maxPtr = &arr[i];
else if (arr[i] < **minPtr)
*minPtr = &arr[i];
}
}
In this case, when you make the assignments, you don't want to dereference the double pointers. Instead, you should assign it with the address of the element you want to show when you dereference them in main().
You don't need to use the double asterisk when initialize the maxPtr and minPtr pointers in the function SaveValue, neither in the for loop body. MaxPtr and minPtr both are double pointers, but is still the memory direction of maxptr in main(). So you only need to dereference them with a single asterisk, to acces the memory direction them points to.
The source correct source code is this:
#include <stdio.h>
/* Correct program to Get Min and Max Value in Array */
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr=arr[0];
*minPtr=arr[0];
for(i=1; i<5; i++)
{
if(arr[i]>*maxPtr)
*maxPtr=arr[i];
else if(arr[i]<*minPtr)
*minPtr=arr[i];
}
}
int main(void)
{
int arr[5]={4, 5, 7, 2, 6};
int *maxptr;
int *minptr;
SaveValue(&maxptr, &minptr, arr);
printf("%d, %d \n", maxptr, minptr);
return 0;
}
When I compile it with GCC and execute it, i get the next output:
7, 2.
Remember that depending of the environment (Operating System, version, compiler, standards) that you use the program results may vary.
So I am trying to figure out why I am getting this error in regards to p thread.
I get the below error when I'm trying to run the code. I know it has to be something with p thread but not sure exactly what it is.
prime.c: In function ‘main’:
prime.c:33: warning: cast to pointer from integer of different size
prime.c: In function ‘isPrime’:
prime.c:50: warning: cast from pointer to integer of different size
any idea of what I'm doing wrong? I am including my code below. Thanks in advance for help.
#include<stdio.h>
#include<stdlib.h>
#include <pthread.h>
int *ptr;
int count;
int n;
void *isPrime(void *argp);
int main(int argc, char *argv[]) {
int i;
int num = 2;
int p;
pthread_t tid;
count = 0;
if (argc == 2 || argc == 3) {
printf("Argument : %s\n", argv[1]);
n = atoi(argv[1]);
if (argc == 3) {
p = atoi(argv[2]);
}
else {
p = 1;
}
ptr = (int *) malloc(n*sizeof(int));
while (count <= n) {
for (i = 1; i <= p; i++)
pthread_create(&tid, NULL, isPrime, (void *)num++);
}
for ( i = 0;i < n; i++) {
printf("%d ", *(ptr+i));
}
}
else {
printf("Invalid number of arguments\n");
}
}
void *isPrime(void *vargp) {
int i,flag = 0;
int num = (int)vargp;
for (i = 2; i <= num/2; i++) {
if (num % i == 0) {
flag = 1;
break;
}
}
if (!flag && count <= n) {
*(ptr + count) = num;
count++;
}
}
Here's the obvious way to avoid the implementation-defined behavior inherent in casting between integers and pointers:
while (count <= n) {
for (i = 1; i <= p; i++) {
int * iptr = malloc(sizeof *iptr);
if ( !iptr ) {
perror("Couldn't allocate memory."); /* Or other failure code */
exit(EXIT_FAILURE);
}
*iptr = num++;
pthread_create(&tid, NULL, isPrime, iptr);
}
}
and then in your thread function:
void *isPrime(void *vargp) {
int * iptr = vargp;
int num = *iptr;
free(iptr);
/* Rest of function */
return NULL;
}
As #WhozCraig points out, this is only one of the thread-related problems in your code.
Edit
As WhozCraig and user3386109 point out, the changes I suggest below introduce a race condition. I haven't encountered this exact use case (passing different values to different threads through a single variable), so I can't offer any useful advice; simply take the explanation for why the warnings occur as what they are.
Original
pthread_create(&tid, NULL, isPrime, (void *)num++);
The expression (void *)num++ attempts to convert the type of the expression num++ to void *; since integers and pointers may have different sizes and representations, this is potentially a bad idea.
Ideally, you should do something more like the following:
{
pthread_create( &tid, NULL, isPrime, (void *) &num );
num++;
}
Unfortunately, (void *) &num++ won't work; the result of the ++ operator isn't an lvalue, so you can't apply the & operator to it.
(void *) &num is converting from one pointer type to void *, which is safer than converting from an integer type to a pointer type.
Then, in the isprime function, you would need to make the corresponding change:
int num = *((int *)vargp);
That is, convert vargp back to a pointer to int and dereference it.
Searched around for one hour. I guess I'd better post the question here.
I simplify the code. The segfault is in the function initMyStruct.
#include "stdlib.h"
typedef struct {
int * arr1;
int * arr2;
} myStruct;
void allocMyStruct (myStruct * a, int num) {
a = malloc(sizeof(myStruct));
a->arr1 = malloc(10*sizeof(int));
a->arr2 = malloc(10*num*sizeof(int));
}
void initMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) a->arr1[i] = 0;
for (i = 0; i < 10*num; i++) a->arr2[i] = -1;
}
void freeMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) free(a->arr1);
for (i = 0; i < 10*num; i++) free(a->arr2);
free(a);
}
int main (void) {
int num = 3;
myStruct * a;
allocMyStruct (a, num);
initMyStruct (a, num);
freeMyStruct (a, num);
return 1;
}
Because you're not keeping the pointer to the newly allocated memory, instead you use an uninitialized pointer and getting undefined behavior.
You pass the a variable into allocMyStruct(), but that call is (like all others) by value, so the new value being assigned to it inside the function does not affect the value of a in main().
Change it so that allocMyStruct() either returns the new pointer value, or takes a pointer to the pointer. I would prefer the former, it's cleaner and using function return values often leads to better code:
myStruct * allocMyStruct(int num)
{
myStruct *p;
if((p = malloc(sizeof *p +
10 * sizeof *p->arr1 +
10 * num * sizeof *p->arr2)) != NULL)
{
p->arr1 = (int *) (p + 1);
p->arr2 = p->arr1 + 10;
}
return p;
}
The above code also streamlines the memory allocation, doing it all in one big malloc() call which is then "sliced" into the three parts you actually need.
If the size of arr1 is always 10 by the way, there's no point in having it dynamically allocated, it should just be int arr1[10]; in the struct declaration.
a is used uninitialized, change to:
myStruct * allocMyStruct (int num) {
myStruct *a;
a = malloc(sizeof(myStruct));
a->arr1 = malloc(10*sizeof(int));
a->arr2 = malloc(10*num*sizeof(int));
return a;
}
myStruct * a = allocMyStruct(num);
Also, there is no need to loop in your free function
void freeMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) free(a->arr1);
for (i = 0; i < 10*num; i++) free(a->arr2);
free(a);
}
Must be
void freeMyStruct (myStruct * a) {
free(a->arr1);
free(a->arr2);
free(a);
}
When you call void allocMyStruct (myStruct * a, int num) the a pointer will be passed as a value and the a parameter is a local copy of your pointer from main , after you change the local a in any of your three functions, it will not change in main.
For this you have to use double pointer as a function argument, so those functions will get an address of a pointer so they can modify it.
#include "stdlib.h"
typedef struct {
int * arr1;
int * arr2;
} myStruct;
void allocMyStruct (myStruct ** a, int num) {
*a = malloc(sizeof(myStruct));
(*a)->arr1 = malloc(10*sizeof(int));
(*a)->arr2 = malloc(10*num*sizeof(int));
}
void initMyStruct (myStruct ** a, int num) {
int i;
for (i = 0; i < 10; i++) (*a)->arr1[i] = 0;
for (i = 0; i < 10*num; i++) (*a)->arr2[i] = -1;
}
void freeMyStruct (myStruct ** a, int num) {
free((*a)->arr1);
free((*a)->arr2);
free(*a);
*a = NULL;
}
int main (void) {
int num = 3;
myStruct * a;
allocMyStruct (&a, num);
initMyStruct (&a, num);
freeMyStruct (&a, num);
return 1;
}
EDIT: Alter Mann is right about multiple freeing of the same address, on linux you would get instant crash for double freeing. And he has a simpler solution.