Reversing the strings from command line with threads in C - segmentation fault - c

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.

Related

Trying to create a multi threaded C program that prints a string in reverse order

I am working on an assignment for my C coding class that requires us to create multiple threads that run different functions. As to ease my confusion, I am trying to do the program one thread at a time, but I am having some trouble. Here is my code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
void * print_string_in_reverse_order(void *str)
{
// This function is called when the new thread is created
printf("%s","In funciton start_routine(). Your string will be printed backwards.");
char *word[50];
strcpy (*word, (char *)str);
int length = strlen(*word);
for (int x = length-1; x >= 0; x--){
printf("%c",&word[x] );
}
pthread_exit(NULL); // exit the thread
}
int main(int argc, char *argv[])
{
/* The main program creates a new thread and then exits. */
pthread_t threadID;
int status;
char input[50];
printf("Enter a string: ");
scanf("%s", input);
printf("In function main(): Creating a new thread\n");
// create a new thread in the calling process
// a function name represents the address of the function
status = pthread_create(&threadID, NULL, print_string_in_reverse_order, (void *)&input);
// After the new thread finish execution
printf("In function main(): The new thread ID = %d\n", threadID);
if (status != 0) {
printf("Oops. pthread create returned error code %d\n", status);
exit(-1);
}
printf("\n");
exit(0);
}
At present, while I have no compiler errors, it does not print anything and does not appear to reverse the string in any way. I am very new to C so I assume it is something like errors with my pointers, but even after several changes and attempts I can't seem to figure out what's wrong. Does anyone have an idea?
If word is supposed to be a char array holding a string, the line
char *word[50];
should be changed to:
char word[50];
Also, the line
strcpy (*word, (char *)str);
should be changed to:
strcpy (word, (char *)str);
In additon, the line
printf("%c",&word[x] );
should be changed to:
printf("%c", word[x] );
Also, before returning from function main(), you must wait for the created thread to finish executing, by adding the following line:
pthread_join( threadID, NULL );
Otherwise, your thread may be terminated prematurely.

segmentation fault on strcpy();

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
typedef struct client
{
int threadid;
int argc;
char *argv[3];
} client;
void exit(int status);
void error(char *msg);
void *threadClient(void *socket_desc);
int main(int argc, char *argv[])
{
client info[10];
pthread_t thread[10];
printf("%s\n%s\n%s\n", argv[0], argv[1], argv[2]);
// Error happens here
for (int i=0; i<=10; i++)
{
info[i].threadid = i;
strcpy(info[i].argv[0], argv[0]);
strcpy(info[i].argv[1], argv[1]);
strcpy(info[i].argv[2], argv[2]);
info[i].argc = argc;
printf("here");
if (pthread_create(&thread[i], NULL, threadClient, (void*)&info[i]) < 0)
{
perror("could not create thread");
return 1;
}
sleep(3);
}
pthread_exit(NULL);
return 0;
}
During the loop, when I am trying to copy the info from argv to my struct I get a segmentation fault. Why does it happen?
Program received signal SIGSEGV, Segmentation fault.
__strcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:296
296 ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.
There are two problem here.
First, your argv array in your info structure is an array of pointers. These start out uninitialized. When you later call strcpy, giving one of these array elements as the first parameter, it expects that pointer to point to valid memory. So you end up dereferencing an uninitialized pointer. This invokes undefined behavior, which in this case manifests as a segfault.
You need to assign something to these pointers. You can either use strdup to make a copy of these strings:
info[i].argv[0] = strdup(argv[0]);
info[i].argv[1] = strdup(argv[1]);
info[i].argv[2] = strdup(argv[2]);
Or, if you don't plan on modifying these values, you can just copy the pointer values directly:
info[i].argv[0] = argv[0];
info[i].argv[1] = argv[1];
info[i].argv[2] = argv[2];
The second issue is an off-by-one error in your loop:
for (int i=0; i<=10; i++){
Because you use <=, your indexes into the array will range from 0 to 10. However, your array only has 10 elements (with indexes 0 to 9), so you're writing past the end of the array. This also invokes undefined behavior.
Change your conditional to < as follows:
for (int i=0; i<10; i++){
Your struct is defined to contain three pointers (char *argv[3]). When you create an array of those structs in the stack (client info[10]) space is reserved for these pointers, among other things. The structs aren't initalized to anything, so the pointers don't point to any sensible memory location. Hence, accessing them as with strcpy(info[i].argv[0], argv[0]); is in error.
Either allocate the space you use explicitly:
info[i].argv[0] = malloc(strlen(argv[0])+1);
strcpy(info[i].argv[0], argv[0]);
Or use strdup() to copy the strings:
info[i].argv[0] = strdup(argv[0]);
Remember to free() the space you allocated afterwards.
Also, I don't think you should declare a function called exit() yourself, it's a standard function and should be in stdlib.h.

C program for counting the number of occurrences of a word in a file using threads getting segmentation fault error

So i have the following problem: Implement a program that gets as arguments a file name followed by words. For each word, create a separate thread that counts its appearances in the given file.Print out the sum of the appearances of all words.
I'm also not sure if my code is really formatted correctly. I'm trying to figure out how to get each word to be counted in the given text file. I am trying to test out this code but I am getting a couple errors from it, the biggest being a segmentation error. If you have any pointers or advice or help, please let me know.
my code is:
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mtx; // used by each of the three threads to prevent other threads from accessing global_sum during their additions
int global_sum = 0;
typedef struct{
char* word;
char* filename;
}MyStruct;
void *count(void*str)
{
MyStruct *struc;
struc = (MyStruct*)str;
const char *myfile = struc->filename;
FILE *f;
int count=0, j;
char buf[50], read[100];
// myfile[strlen(myfile)-1]='\0';
if(!(f=fopen(myfile,"rt"))){
printf("Wrong file name");
}
else
printf("File opened successfully\n");
for(j=0; fgets(read, 10, f)!=NULL; j++){
if (strcmp(read[j],struc->word)==0)
count++;
}
printf("the no of words is: %d \n",count);
pthread_mutex_lock(&mtx); // lock the mutex, to prevent other threads from accessing global_sum
global_sum += count; // add thread's count result to global_sum
pthread_mutex_unlock(&mtx); // unlock the mutex, to allow other threads to access the variable
}
int main(int argc, char* argv[]) {
int i;
MyStruct str;
pthread_mutex_init(&mtx, NULL); // initialize mutex
pthread_t threads[argc-1]; // declare threads array
for (i=0;i<argc-2;i++){
str.filename = argv[1];
str.word = argv[i+2];
pthread_create(&threads[i], NULL, count, &str);
}
for (i = 0; i < argc-1; ++i)
pthread_join(threads[i], NULL);
printf("The global sum is %d.\n", global_sum); // print global sum
pthread_mutex_destroy(&mtx); // destroy the mutex
return 0;
}
The second good bit of advice for today is to look carefully at the warnings that your compiler gives you and take heed of them. strcmp(read[j],struc->word) Your compiler must have warned you that that is wrong. You are passing a single char as the first parameter instead of const char *. That'll almost certainly result in a seg fault. – kaylum

weird behaviour when working with double pointers

I need help to understand why in this little program i cannot manipulate correctly pointers:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void change(char *s[][15]){
int i=0;
while(i<5){
if(s[i][0]=='B') s[i][0]='v';
i++;
}
}
/*My code is supposed to allocate dynamically 5 arrays of 15 chars each
(like tab[5][15])and then put a message on them and try to modify the messages.
In this particular case i'm trying to change the first letter of each string to 'V'.
I'm doing this little experience because of another program
in which i have difficulties accessing double arrays*/
int main(){
int i;
char **s;
s =malloc(5*sizeof(char*));
for(i=0;i<5;i++){
s[i]=malloc(15*sizeof(char));
sprintf(s[i],"Bonjour%d",i);
}
change(s);
for(i=0;i<5;i++){
printf("%s\n",s[i]);
}
return 0;
}
I was expecting :
Vonjour0
Vonjour1
Vonjour2
Vonjour3
Vonjour4
but I get :
Bonjour0
Bonjour1
Bonjour2
Bonjour3
Bonjour4
I'm testing this little code for another program and I don't get why the arrays don't change.
In my other program I can't access the double pointer or print the content.
so my question is : why in this program I can't modify the content of the arrays ?
Your change method needs to use "char** s" instead of char *s[][15]. This is because your method is expecting a pointer to a multi-dimensional array. This is immutable as a result, since your original data type for the string is a pointer to an array of strings (IE: An array of chars).
Hopefully that was clear.
It should be
char **change(char **s){
int i=0;
while(i<5){
if(s[i][0]=='B') s[i][0]='v';
i++;
}
return s;
}
You only need to change the function argument to char *s[].
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void change(char *s[]){
int i=0;
while(i<5){
if(s[i][0]=='B') s[i][0]='v';
i++;
}
}
int main(){
int i;
char **s;
s =malloc(5*sizeof(char*));
for(i=0;i<5;i++){
s[i]=malloc(15*sizeof(char));
sprintf(s[i],"Bonjour%d",i);
}
change(s);
for(i=0;i<5;i++){
printf("%s\n",s[i]);
}
return 0;
}
Program output:
vonjour0
vonjour1
vonjour2
vonjour3
vonjour4

How to make a copy of a string and return its address, assign that to a pointer and print the new string in C? [duplicate]

This question already has answers here:
Passing address of array as a function parameter
(6 answers)
Closed 9 years ago.
I'm writing a function that gets a string, allocates memory on the heap that's enough to create a copy, creates a copy and returns the address of the beginning of the new copy.
In main I would like to be able to print the new copy and afterwards use free() to free the memory. I think the actual function works although I am not the char pointer has to be static, or does it?
The code in main does not work fine...
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int make_copy(char arr[]);
int main()
{
char arrr[]={'a','b','c','d','e','f','\0'};
char *ptr;
ptr=make_copy(arrr);
printf("%s",ptr);
getchar();
return 0;
}
int make_copy(char arr[])
{
static char *str_ptr;
str_ptr=(char*)malloc(sizeof(arr));
int i=0;
for(;i<sizeof str_ptr/sizeof(char);i++)
str_ptr[i]=arr[i];
return (int)str_ptr;
}
OK, so based on the comments. A revised version:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={"abcdef\0"};
char *ptr=make_copy(arrr);
printf("%s",ptr);
getchar();
return 0;
}
char* make_copy(char arr[])
{
static char *str_ptr;
str_ptr=(char*)malloc(strlen(arr)+1);
int i=0;
for(;i<strlen(arr)+1;i++)
str_ptr[i]=arr[i];
return str_ptr;
}
Or even better:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={"abcdef\0"};
printf("%s",make_copy(arrr));
getchar();
return 0;
}
char* make_copy(char arr[])
{
char *str_ptr;
str_ptr=(char*)malloc(strlen(arr)+1);
return strcpy(str_ptr,arr);
}
You're on the right track, but there are some issues with your code:
Don't use int when you mean char *. That's just wrong.
Don't list characters when defining a string, write char arrr[] = "abcdef";
Don't scale string alloations by sizeof (char); that's always 1 so it's pointless.
Don't re-implement strcpy() to copy a string.
Don't cast the return value of malloc() in C.
Don't make local variables static for no reason.
Don't use sizeof on an array passed to a function; it doesn't work. You must use strlen().
Don't omit including space for the string terminator, you must add 1 to the length of the string.
UPDATE Your third attempt is getting closer. :) Here's how I would write it:
char * make_copy(const char *s)
{
if(s != NULL)
{
const size_t size = strlen(s) + 1;
char *d = malloc(size);
if(d != NULL)
strcpy(d, s);
return d;
}
return NULL;
}
This gracefully handles a NULL argument, and checks that the memory allocation succeeded before using the memory.
First, don't use sizeof to determine the size of your string in make_copy, use strlen.
Second, why are you converting a pointer (char*) to an integer? A char* is already a pointer (a memory address), as you can see if you do printf("address: %x\n", ptr);.
sizeof(arr) will not give the exact size. pass the length of array to the function if you want to compute array size.
When pass the array to function it will decay to pointer, we cannot find the array size using pointer.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strdup(const char *str)
{
char *s = (char*)malloc(strlen(str)+1);
if (s == NULL) return NULL;
return strcpy(s, str);
}
int main()
{
char *s = strdup("hello world");
puts(s);
free(s);
}
Points
~ return char* inside of int.
~ you can free the memory using below line
if(make_copy!=NULL)
free(make_copy)
Below is the modified code.
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={'a','b','c','d','e','f','\0'};
char *ptr;
ptr=make_copy(arrr,sizeof(arrr)/sizeof(char));
printf("%s",ptr);
printf("%p\n %p",ptr,arrr);
getchar();
return 0;
}
char* make_copy(char arr[],int size)
{
char *str_ptr=NULL;
str_ptr=(char*)malloc(size+1);
int i=0;
for(;i<size;i++)
str_ptr[i]=arr[i];
str_ptr[i]=0;
return str_ptr;
}

Resources