I started a week ago understanding and working with semaphores and shared memory, and actually created this program; the problem is I can't find anything wrong with it. I've been looking at it for hours and everything seems correct. The code compiles and i can create the build but when I execute it nothing happens.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <semaphore.h>
#define MAXCHILDS 4
#define MAX_SIZE 10
#define MAX_WRITES 4
typedef struct{
int m[MAX_SIZE][MAX_SIZE];
} matrix;
/*fork variables*/
pid_t child[MAXCHILDS];
/*semphores variables */
sem_t *empty, *full, * mutex;
/*share memory id*/
int shmid;
/*shared memory array pointer */
matrix * sh_mem;
/*pointer to matrix*/
int **p;
void init(){
/*create pointer to matrix*/
p = &sh_mem->m;
/*semaphores unlink and creation */
sem_unlink("EMPTY");
empty=sem_open("EMPTY",O_CREAT|O_EXCL,0700,MAX_WRITES);
sem_unlink("FULL");
full=sem_open("FULL",O_CREAT|O_EXCL,0700,0);
sem_unlink("MUTEX");
mutex=sem_open("MUTEX",O_CREAT|O_EXCL,0700,1);
/*initialize shared memory */
shmid = shmget(IPC_PRIVATE,sizeof(matrix),IPC_CREAT|0777);
/*map shared memory*/
sh_mem = (matrix*)shmat(shmid,NULL,0);
if(sh_mem== (matrix*)(-1)){
perror("shmat");
}
}
void writer(int ** m){
int i,k;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
m[i][k] = 0;
}
}
}
void reader(int **m){
int i = 0;
int k = 0;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
printf(m[i][k]);
}
printf("\n");
}
}
void terminate() {
sem_close(empty);
sem_close(full);
sem_close(mutex);
sem_unlink("EMPTY");
sem_unlink("FULL");
sem_unlink("MUTEX");
shmctl(shmid, IPC_RMID, NULL);
}
int main(int argc, char **argv)
{
int i;
init();
for(i = 0;i<MAXCHILDS;i++){
if ((child[i] = fork()) < 0) // error occured
{
perror("Fork Failed");
exit(1);
}
if ((child[i] = fork())==0){
writer(sh_mem->m);
exit(0);
}
}
/*father*/
reader(sh_mem->m);
wait(NULL);
terminate();
return 0;
}
The children are supposed to write the the matrix in shared memory, and the father is supposed to read the shared memory array and the print the matrix.
Can you help me with this? Thanks for the help ...
The primary error here is that reader and writer take a different type of argument than you're passing to them, as gcc -Wall points out:
test.c: In function ‘main’:
test.c:92:13: warning: passing argument 1 of ‘writer’ from incompatible pointer type [enabled by default]
test.c:49:6: note: expected ‘int **’ but argument is of type ‘int (*)[10]’
test.c:97:5: warning: passing argument 1 of ‘reader’ from incompatible pointer type [enabled by default]
test.c:58:6: note: expected ‘int **’ but argument is of type ‘int (*)[10]’
As provided, the program segfaulted in the parent and every child. When I changed the parameter type of reader and writer from int **m to int m[MAX_SIZE][MAX_SIZE] (along with the fixes below), the program ran successfully, as far as I can tell.
There are a number of other errors:
You need to #include <sys/wait.h>.
The global int **p isn't used and its initialization has the same type error as the reader and writer functions did.
The printf call in reader needs a format string; I used "%d ".
As Jonathan Leffler pointed out, you need to call fork() only once each time through the loop in main.
All but the last of those were highlighted by compiler warnings.
In studying why this program was failing, I also used strace -f to identify which syscalls and processes were actually busted. The semaphore-related syscalls, for example, appear to be returning successfully--although as Jonathan pointed out, you should check their return values for errors, because failing as early as possible makes it much easier to debug problems.
Related
#include <stdio.h>
#include <stdlib.h>
// Thread Declarations
#include <pthread.h>
pthread_t monitor_thread;
void *Get_Monitor_Data(void *BM_params);
// this is my struct ///
typedef struct
{
HCORE BM_cores[0];
int total_cores;
} BM_PARAMS;
BM_PARAMS BM_Dat;
int Start_monitor(void)
{
int RETVAL=0;
RETVAL = pthread_create(&monitor_thread, NULL, Get_Monitor_Data,(void*)BM_Dat);
if(RETVAL !=0)
{
printf("Error Starting Thread \n");
}
return 0;
}
void *Get_Monitor_Data (void *BM_Dat) // Bus Monitor Thread
{
BM_PARAMS*monitor_params;
int no_of_cores=0;
monitor_params = (BM_PARAMS *) BM_Dat;
BTICard_CardReset(*monitor_params->BM_cores);// reset card if required
return 0;
}
The pthread create portion is giving error of "cannot convert to a pointer type"
is there anything wrong which i am doing?
i need to pass a structure to the P thread function as argument, how can i do that?
You're trying to cast BM_Dat which has structure type to a void *. A struct cannot be converted to a pointer. You can however pass the address of BM_Dat:
RETVAL = pthread_create(&monitor_thread, NULL, Get_Monitor_Data, &BM_Dat);
A BM_PARAMS * can be converted to a void * (implicitly in fact), and in fact your thread function converts the parameter to this type.
Although I think I have more than one issue in this code, I want to solve my compiler error first. Thank you in advance for any suggestions. I will try to address run errors next.
The Error:
fuzzer.c: In function ‘main’:
fuzzer.c:26:25: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
charArray[arraySize-1] = NULL; /*make sure charArray[] is a string array that has a size of arraySize */
^
The Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
int main(void)
{
int fuzzNum = 100;
char buffer[1000], *charArray;
int status, ret, i, j, retCode, arraySize; /* */
time_t t;
FILE *fin;
FILE *fout;
srand((unsigned) time(&t)); /* randomize the initial seed */
for(i=0; i<fuzzNum; i++)
{
charArray = (char *) malloc(arraySize);
for (j=0; j< arraySize; j++)
charArray[j] = 'A';
charArray[arraySize-1] = NULL;
/*make sure charArray[] is a string array that has a size of arraySize */
/* open and read the cross.jpg file as a binary format file*/
fin=fopen("./cross.jpg","rb" );
/*generate a variable file name*/
char fileName[30]; int n;
sprintf(fileName, "crashed-%d.jpg", n);
fout=fopen("./test.jpg","wb");
/* execute the jpg2bmp file to process the test.jpg file*/
char comBuf[200];
sprintf(comBuf, "./jpg2bmp test.jpg temp.bmp");
ret=system(comBuf);
free(charArray); /* must free memory for repeat testing! */
ret=system(buffer);
wait(&status);
retCode=WEXITSTATUS(ret);
if ( retCode == 128+11 || retCode ==128+6) /* segmentation fault (11) or Abort (6) */
{
printf("retCode=%d, arraySize = %d", retCode, arraySize);
fflush(stdout); /*make sure output is print out immediately ! */
}
}
return 0;
}
First of all, this is a warning, and not an error. Your code should compile successfully in the least, if this warning is the only issue the compiler produces during the build process. However, if you want to overcome this issue, you can simply change:
charArray[arraySize-1] = NULL;
To:
charArray[arraySize-1] = 0;
While charArray is a pointer that points to the first memory space in the array, charArray[i], where i represents a counter as an example here, is of data type int. Now, NULL is used when a pointer points to nothing, or in computer terms, to the ground. Therefore, the compiler warns you that you are storing a pointer attribute in a non-pointer memory space (Sorry for the really por choice of words, if there is anything wrong with it, please correct me in the comments box).
The above code change should resolve the warning your compiler produces.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
sem_t s1, s2;
pthread_t foo_tid, bar_tid;
void *foo(void*) {
while(1) {
sem_wait(&s1);
printf("HI ");
sem_post(&s2);
}
}
void *bar(void*) {
while(1) {
sem_wait(&s2);
printf("HO ");
sem_post(&s1);
}
}
int main() {
sem_init(&s1, 0, 0);
sem_getvalue(&s1, &foo_tid);
sem_init(&s2, 0, 0);
sem_getvalue(&s2, &bar_tid);
pthread_create(&foo_tid, NULL, foo, NULL);
pthread_create(&bar_tid, NULL, bar, NULL);
return 0;
}
I'm trying to get the output of the semaphores s1 and s2. But I keep getting these errors:
sema.c: In function 'main':
sema.c:29:3: warning: passing argument 2 of 'sem_getvalue' from incompatible pointer type [enabled by default]
In file included from sema.c:6:0:
/usr/include/semaphore.h:72:12: note: expected 'int * __restrict__' but argument is of type 'pthread_t *'
sema.c:31:3: warning: passing argument 2 of 'sem_getvalue' from incompatible pointer type [enabled by default]
In file included from sema.c:6:0:
/usr/include/semaphore.h:72:12: note: expected 'int * __restrict__' but argument is of type 'pthread_t *'`
I just haven not been able to get rid of this error. If anyone could help me out with this, that'd be greatly appreciated!
From sem_getvalue, values should be int :
Declare int s1_val, s2_val;
sem_init(&s1, 0, 0);
sem_getvalue(&s1, &s1_val);
sem_init(&s2, 0, 0);
sem_getvalue(&s2, &s2_val);
The second parameter is expected to be a pointer to int, where as you are passing in the address of a pthread_t. A pthread_t is not an int on your system.
I have some troubles when using strcpy to copy an array of string inside a double pointer with allocated memory, but i can't understand why i get segmentation fault even if i have previously allocated memory.
Here is the code:
#include <stdio.h>
#include <string.h>
typedef struct Students {
int q_exams;
char **done_exams;
}Students;
int main() {
Students a;
int i;
char support[30];
printf("how many exams have you done ?\n");
scanf("%d",&(a.q_exams));
a.done_exams=malloc(sizeof(char*)*a.q_exams);
if(a.done_exams==NULL)
{
printf("out of memory\n");
return 0;
}
for(i=0;i<a.q_exams;i++)
{
printf("Insert the name of the exam\n");
scanf("%28s",support);
a.done_exams[i]=malloc(strlen(support)+1);
if(a.done_exams[i]==NULL)
{
printf("out of memory\n");
return 0;
}
strcpy(a.done_exams[i][0],support);
fflush(stdin);
}
return 0;
}
You need to pass an address of the initial character to strcpy, either like this
strcpy(&a.done_exams[i][0],support);
// ^
// Add an ampersand
or equivalently like this:
strcpy(a.done_exams[i] , support);
// ^
// Remove the second index
Currently, your code passes the value* of the initial character, rather than its address.
* The value is undefined at the time as well, but it is not the primary cause, because you should not be passing value at all.
This code is fixed
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Students {
int q_exams;
char **done_exams;
} Students;
int main()
{
Students a;
int i;
char support[49];
printf("how many exams have you done ?\n");
scanf("%d",&(a.q_exams));
a.done_exams = malloc(sizeof(char*) * a.q_exams);
if(a.done_exams==NULL)
{
printf("out of memory\n");
return 0;
}
for(i = 0 ; i < a.q_exams ; i++)
{
printf("Insert the name of the exam\n");
scanf("%48s",support);
a.done_exams[i] = malloc(strlen(support)+1);
if(a.done_exams[i] == NULL)
{
printf("out of memory\n");
return 0;
}
strcpy(a.done_exams[i]/*[0]*/, support);
/* ^ ^- this is wrong
* + pass the address to the array not the first element value
*
* if you had warnings turned on you would have seen this
*/
fflush(stdin);
}
return 0;
}
notice that
scanf("%48s", support);
requires
char support[49];
which is also fixed in the code.
See the man page of strcpy().
The first argument should be of type char *.
As per your code, the argument [a.done_exams[i][0]] is of type char. You need to pass a char * [starting address of the destination] actually.
Change your code to
strcpy(a.done_exams[i],support);
The
strcpy(a.done_exams[i][0],support);
should be
strcpy(a.done_exams[i],support);
or
strcpy(&a.done_exams[i][0],support);
My advice would be to always compile with compiler warnings turned on. My compiler (gcc) does a very good job of catching the problem and telling you exactly what needs to be done to fix it:
test.c:37:12: warning: incompatible integer to pointer conversion passing 'char' to
parameter of type 'char *'; take the address with & [-Wint-conversion]
strcpy(a.done_exams[i][0],support);
^~~~~~~~~~~~~~~~~~
&
P.S. You are also missing some #includes:
#include <stdlib.h>
#include <string.h>
I am new with threads.
I am trying to make a C program that reverses the string given from the command line and create a thread that does this for each one . When I run it gives me Segmentation fault .
Here is the code:
#include <stdio.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdlib.h>
#include <fcntl.h>
char* final[1000];
pthread_mutex_t *mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t p[];
void *reverse(void* arg){
char* s[100];
char* temp;
int i;
strcpy(s,(char*)arg);
printf("S este %s",s);
for(i=0;i<=strlen(s)/2;i++){
strcpy(temp,s[i]);
strcpy(s[i],s[strlen(s)-i-1]);
strcpy(s[strlen(s)-i-1],temp);
}
sleep(1);
pthread_mutex_lock(&mutex);
strcat(final,s);
printf("Intermediar %s",s);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main(int argc,char* argv[]) {
int i;
int n = argc;
strcpy(final,"");
for(i=1;i<n-2;i++){
pthread_create(&p[i],NULL,reverse,argv[i]);
}
for(i=1;i<n-2;i++){
pthread_join(p[i],NULL);
}
//printf("Sirul final este %s",final);
return 0;
}
Does anyone know a good site that could help me learn threads ?
Thanks !
char* final[1000];
is an array (with 1000 elements) of pointer to char, you want an array of char:
char final[1000];
the same problem with this array:
char* s[100];
temp is declared as a pointer, but you use it as an array with size 1
declare the mutex without the * ,remove the initialization and add in main:
pthread_mutex_init(&mutex, NULL);
you should also add a number to the array definition of pthread_t
You never initialize temp, so the call strcpy(temp, s[i]); causes undefined behavior.
Your treatment of s is also very confusing, the copying of arg (a string) into the memory used by s (an array of string pointers) is not valid. Just because you can cast away a warning doesn't mean you're doing something sensible.