I'm relatively new to C and I'm starting to work with threads and the command line; I just need help with a bit of debugging and error handling. I've run into a segmentation fault every time I try and process the code. It works fine if there is an argument for argv[1]. However, when trying to catch any errors, such as only entering "./example" and nothing else, it finds a segmentation fault.
I have tried variations of the following code to no avail, including looking to see if argc < 1:
int main(int argc, char * argv[]){
pthread_t worker1;
int in;
if(arv[1] == NULL){
printf("ERROR HERE");
}else{
in = strtol(argv[1], &endptr, 10);
}
if(*endptr > in || *endptr == in){
printf("please eneter a number larger than zero");
return EXIT_FAILURE;
}else{
pthread_create(&worker1, NULL, worker, &in);
pthread_join(worker1, NULL);
}
return EXIT_SUCCESS;
}
Below is the current code which I am using, I'm pretty sure it's something small that I'm overlooking. I have never used strtol before and was using atoi before, I have heard it's a better practice to do this. I'm relatively sure the error is in the code provided as when I test the thread function, it works fine; if more is needed please let me know!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
int main(int argc, char * argv[]){
pthread_t worker1;
int in = strtol(argv[1], &endptr, 10);
if(*endptr > in || *endptr == in){
printf("please eneter a number larger than zero");
return EXIT_FAILURE;
}else{
pthread_create(&worker1, NULL, worker, &in);
pthread_join(worker1, NULL);
}
return EXIT_SUCCESS;
}
You are trying to access an array without doing any kind of bounds checking first:
int main(int argc, char * argv[]){
pthread_t worker1;
int in = strtol(argv[1], &endptr, 10);
...
Who is to say that argv[1] exists? Certainly not your program, because it doesn't check that condition first. Add a check on argc to make sure you are getting the number of arguments you expect before trying to use them.
if (argc > 1) {
int in = strtol(argv[1], &endptr, 10);
}
Related
I'm currently trying to implement a chat server/shoutbox via named pipes. The server takes the name of the pipes as a command line argument. It then proceeds with creating the pipes and opens them for reading. The other processes open the pipe for writing and ask the user for input (client). Once the user hits enter, the message is written to the pipe. When the user hits enter without entering any character the client closes the pipe and exits. The server does not need to support reconnects and the clients need to connect in the order they have been specified on the command line. This works fine for exactly one client, but not for a second or third one. My code to implement this behaviour is the following:
Side note: the hashtag plus client name serves to identify the client. It is sent in the beginning to register a client on the server, so that it knows to which client it is talking. In the file fifo.h respectively fifo.c there are my custom implementations of create_fifo, open_fifo and close_fifo which handle the creation, opening and closing of the fifos.
Edit: I'm a step closer now to what I have to achieve. I had to add a few lines to the code which I will mark in the code below by adding a comment. The only problem that persists is that the server does not recognize when the second user leaves the server first and then the first one does. So it leaves the pipes open and does not return to the clean_up function.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <string.h>
#include "fifo.h"
void clean_up(int* fifos, char** argv, int n);
int main(int argc, char** argv){
int clients = argc - 1;
int fifos[clients];
char reg[clients][PIPE_BUF];
fd_set active_clients;
FD_ZERO(&active_clients);
for (int i = 0; i < clients; i++){
create_fifo(argv[i + 1]);
fifos[i] = open_fifo(argv[i + 1], O_RDONLY);
FD_SET(fifos[i], &active_clients);
}
fd_set tmpset;
memcpy(&tmpset, &active_clients, sizeof(fd_set)); // <-- I added this line
setbuf(stdout, NULL);
while (clients > 0){
if (select(fifos[clients - 1] + 1, &active_clients, NULL, NULL, NULL) < 0){
fprintf(stderr, "Failed to select fifos\n");
clean_up(fifos, argv, argc);
return EXIT_FAILURE;
}
for (int i = 0; i < clients; i++){
if (FD_ISSET(fifos[i], &active_clients)){
char buf[PIPE_BUF];
read(fifos[i], buf, sizeof(buf));
if (buf[0] == '#'){
strncpy(reg[i], buf + 1, PIPE_BUF);
printf("%s joined the server\n", reg[i]);
continue;
}
if (buf[0] == '\n'){
clients--;
FD_CLR(fifos[i], &tmpset);
FD_CLR(fifos[i], &active_clients);
printf("%s left the server\n", reg[i]);
continue;
}
printf("%s: %s", reg[i], buf);
}
}
memcpy(&active_clients, &tmpset, sizeof(fd_set)); // <-- I added this line
}
clean_up(fifos, argv, argc);
return EXIT_SUCCESS;
}
void clean_up(int* fifos, char** argv, int n){
for (int i = 1; i < n; i++){
close(fifos[i - 1]);
close_fifo(argv[i]);
}
}
And the client side is implemented like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "fifo.h"
int main(int argc, char** argv){
int fp = open_fifo(argv[argc - 1], O_WRONLY);
char id[BUF_SIZE] = "";
char* client_name = argv[argc - 1];
strncat(id, "#", 1);
strncat(id, client_name, strlen(client_name));
write(fp, id, strlen(id) + 1);
while (1){
char buf[PIPE_BUF];
printf("Message: ");
fgets(buf, PIPE_BUF, stdin);
write(fp, buf, strlen(buf) + 1);
if (buf[0] == '\n'){
break;
}
}
close(fp);
return EXIT_SUCCESS;
}
As far as I figured it out, it has something to do with the select command. It blocks until one of the fifos has some input ready, but only for the first client that sends a message. Unfortunately it does not unblock for the other clients. Additionally, I don't know whether my argument passed for nfds on the select command is the right one. I did also try to put in FD_SETSIZE but that didn't change much. Does anybody know what I am doing wrong here?
Programming Language C
below is the code that uses multiple threads to print out a file. There are no errors, however the code doesn't work correctly. However, when compiled it shows this warning 5 times:
'cast from pointer to integer of different size'
I've tried everything I can think of to resolve this issue, but haven't been success and now are just shooting in the dark. Does anyone see where my mistake is? Any help is greatly appreciated and will gladly provide any other information upon request.
Thanks.
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#define NUM_THREAD 4
struct fileParams {
int fd;
int size;
};
void *printFile(void *stuff)
{
struct fileParams *params = stuff;
int addr;
addr=(unsigned char *)mmap(NULL, (int) ¶ms->size, PROT_READ,
MAP_PRIVATE,(int) ¶ms->fd,0);
write(STDOUT_FILENO, addr, (int)¶ms->size);
}
int main (int argc, char * argv[])
{
pthread_t threads[NUM_THREAD];
unsigned char *addr;
int fd,rc;
struct stat sb;
int numCPU=sysconf(_SC_NPROCESSORS_ONLN);
struct fileParams params;
printf("Number of aviable cores: %d\n",numCPU);
printf("Using 4 processors\n");
if (argc != 2 || strcmp(argv[1], "—help") == 0)
printf("Usage: %s file\n", argv[0]);
fd=open(argv[1],O_RDONLY);
if (fd == -1)
{
printf("File open fdailed.\n");
exit(EXIT_FAILURE);
}
if (fstat(fd, &sb) == -1)
{
printf ("fstat error\n");
exit(EXIT_FAILURE);
}
params.fd=fd;
params.size=sb.st_size/4;
for (int n = 0; n<4; n++)
rc=pthread_create(&threads[n],NULL,printFile,¶ms);
exit(EXIT_SUCCESS);
}
You need provide inputs to functions that match the function - passing pointers where integers are wanted (or the other way around) will generate warnings or errors depending on compile options.
mmap takes an size_t as the 2nd parameter, but you are giving it a cast int to a pointer (¶ms->size), the same with mmaps 5th parameter.
Get rid of the '&' so it is just a int.
mmap also returns a void *, which you are then assigning to addr (an int).
Change int to a void * pointer type which should also fix the 5th warning.
I'm trying to write the simpliest client in RPC with this code:
#include <stdio.h>
#include <stdlib.h>
#include <rpc/rpc.h>
int main(int argc, char *argv[]){
int stat;
char out;
char in='f';
if(stat=callrpc(argv[1],0x20000001, 1, 1, (xdrproc_t)xdr_void, &in, (xdrproc_t)xdr_char, &out)!=0){
clnt_perrno(stat);
exit(1);
}
exit(0);
}
It compiles, but when I try to run it, it gives me a "RPC: Can't encode arguments"
EDIT: Actually the server do not recieve any argument neither it send back anything, that's why I put a xdr_void added &in and &out to avoid segmentation fault error.
You are missing some parentheses:
if (stat = callrpc(...) != 0)
is evaluated to
if (stat = (callrpc(...) != 0))
which always assigns 1 to stat in case of an error, which is RPC_CANTENCODEARGS. You need
if ((stat = callrpc(...)) != 0)
to get the real error code and message printed in
clnt_perrno(stat);
I'm trying to write a C program, that make user able to write stuff in a file. My Problem is that after making and running the program the file stay empty ?? any idea how can I solve this.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
// the user should give a file to write the file
int main (int argc , char**argv)
{
int fd; // file descriptor
char ret; // the character
int offset;
if(argc != 2) {
printf("You have to give the name or the path of the file to work with \n");
printf("Exiting the program \n")
return -1;
}
fd = open (argv[1], O_WRONLY/*write*/|O_CREAT/*create if not found */, S_IRUSR|S_IWUSR/*user can read and write*/);
if (fd == -1) {
printf("can'T open the file ");
return -1;
}
printf("At wich position you want to start ");
scanf("%d",&offset);
lseek(fd,offset,SEEK_SET);
while(1) {
ret = getchar();
if(ret == '1') {
printf("closing the file");
close (fd);
return 1;
}
else
write (fd,red, sizeof(char));
}
return 0;
}
thanks in advance for you help.
I have made some changes,this should work:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main (int argc , char**argv)
{
int fd; // file descriptor
char ret; // the character
int offset;
if(argc != 2){
printf("You have to give the name or the path of the file to work with \n");
printf("Exiting the program \n"); **//There was ';' missing here**
return -1;
}
fd = open (argv[1], O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
if (fd == -1) {
printf("can'T open the file ");
return -1;
}
printf("At wich position you want to start ");
scanf("%d",&offset);
lseek(fd,offset,SEEK_SET);
while(1){
ret = getchar();
if(ret == '1'){
printf("closing the file");
close (fd);
return 1;
}
else
write (fd,&ret, sizeof(char)); **//red has been changed to &ret**
}
return 0;
}
One error I can notice, the call of write function:
write (fd,red, sizeof(char));
should be:
write (fd, &red, sizeof(char));
You forgot & before red, write need address.
syntax of write: int write( int handle, void *buffer, int nbyte );
This will cause an undefined behavior in your code at run time
Edit: in write function you are using red that is not defined, I think it should be ret variable in your code. correct it as write (fd, &ret, sizeof(char));
second, you forgot ; after printf("Exiting the program \n") in if, but I also think its mistake while posting question as you says you are getting run time error.
side note: If you are using gcc compiler then you can use gcc -Wall -pedantic to generate warnings
It should be:
write (fd,&ret, sizeof(char));
write takes the pointer to the memory position, and since ret is a single char, you need to pass a pointer to it.
I have tried for a long time and cannot figure out where this 'core dumped' is coming from. I am using c on cygwin. Commenting out the threads gets rid of the problem but commenting out the entire code in the thread does nothing. Could this have something to do with the calling of the thread?? It appeared to be working then this suddenly happened. I have deleted most of the code and this is what is left-
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <pthread.h>
#include <string.h>
typedef enum {true=1, false=0} bool;
void *piThread(void *arg);
int finished;
int main(int argc, char *argv[])
{
int i;
int threads;
bool display = false;
long double pI = 0.0;
void *status = malloc(sizeof(int));
pthread_t thread_id[threads];
if(argc < 2) {printf("not enough arguments"); exit(1);
}else threads = atoi(argv[1]);
if(argc == 3)
if (strcmp(argv[2], "b") == 0)
display = true;
for(i=0; i<threads; i++)
{
pthread_create(&thread_id[i], NULL, piThread, NULL);
pthread_join(thread_id[i], &status);
printf("pi: %Lf\n", pI);
}
return 0;
}
void *piThread(void *arg)
{
int number = 0;
number = 74;
pthread_exit((void*)number);
}
This is causing an aborted error.
Stack trace:
Frame Function Args
0028A6A4 76821184 (000000D0, 0000EA60, 00000000, 0028A7D8)
0028A6B8 76821138 (000000D0, 0000EA60, 000000A4, 0028A7B4)
0028A7D8 610DBE29 (00000000, FFFFFFFE, 77403B23, 77403B4E)
0028A8C8 610D915E (00000000, 0028A918, 00000001, 00000000)
0028A928 610D962E (76D709CD, 7427AED9, 00000003, 00000006)
0028A9D8 610D9780 (000011E8, 00000006, 002B002B, 800483D8)
0028A9F8 610D97AC (00000006, 0028CE80, FFFDE000, 00000000)
0028AA28 610D9A85 (000000D0, 0028ABF0, 0028AA58, 610FA223)
End of stack trace
I have no idea what is wrong!!
command line is-
gcc pi.exe 100
any combination ABOVE 26 causes this fault.
Thank you for any insight
You are allocating thread_id before 'threads' is defined. This should fix that problem at least.
if(argc < 2) {printf("not enough arguments"); exit(1);
}else threads = atoi(argv[1]);
pthread_t thread_id[threads];