I am trying to do an assignment in which I am to use multiple threads to sort input from a file, but when I try to use the array of structs to store the information I need to recover after the threads, I get a segmentation fault. I am not sure why it is causing the fault, as according to the sources I have.
This is the main file, Threads.c The seg fault is in the for loop, and the causing line is desginated by a comment. Sort Method is another function I did not in
#include "threads.h"
Threads* threadArray[4];
int linesPerThread;
int extraLines;
main(int argc, char *argv[]){
int n;
if( argc != 4){
printf("Wrong Number of Arguements!\n");
return;
}
n = atoi(argv[1]);
char *inName = argv[2];
*threadArray = (Threads*) (*threadArray, n*sizeof(Threads));
FILE* file = fopen(inName, "r");
if(!file){
printf("invalid file Name \n");
return;}
int lines = 0;
char xyz[5000]; //makes fgets happy
while(fgets(xyz, 5000, file) != NULL){
lines = lines+1;
}
fclose(file);
linesPerThread = lines / n;
extraLines = lines - linesPerThread;
int i =0;
int methodCounter =1;
printf("Right before Loop \n \n");
for(i; i < n; i++){
printf("first part of loop \n");
\\The ling below here Seg Faults.
(*threadArray + i)->id = i;
printf("right after first ThreadArray access \n");
if(methodCounter < 3){
printf("method counter 1\n");
(*threadArray+i)->methodID = methodCounter;
methodCounter++;
}else{
printf("method counter condition 2 \n");
(*threadArray + i)->methodID = 3;
methodCounter = 1;}
if(extraLines > 0){
printf("extra Lines condition 1 \n");
(*threadArray+i)->lines = linesPerThread +1;
extraLines= extraLines -1;
}else{
printf("extraLines condition 2 \n");
(*threadArray+i)->lines = linesPerThread;
}
printf("Right before Thread Creation \n \n");
pthread_t tID;
pthread_create(&tID, NULL, sortMethod, (void*) &((*threadArray+i)->id));
(*threadArray+i)->threadID = tID;
printf("right after thread creation \n \n");
}
printf("right after loop \n \n");
int c=0;
printf("before thread joining \n");
for(c; c< n; c++){
pthread_join( (*threadArray+ c)->threadID, NULL);
}
}
And this is the header file, Threads.h
#include <sys/time.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int id;
int lines;
pthread_t threadID;
int methodID;
}Threads;
void* sortMethod(void*ptr);
int main(int argc, char *argv[]);
Any help you can offer would be greatly appreciated.
In the line
*threadArray = (Threads*) (*threadArray, n*sizeof(Threads));
you are setting threadArray[0] to (Threads*)(n*sizeof(Threads). You probably want a realloc or a calloc in that line.
As it stands,
(*threadArray, n*sizeof(Threads))
is a comma-expression, and the value of that comma-expression is cast to Threads*.
Since you never allocated memory to any of the elements of threadArray,
(*threadArray + i)->id = i;
dereferences invalid pointers. Since the array is static, the pointers are originally initialised to null pointers, you only set threadArray[0] to a different value (but that doesn't point to valid memory either, in all probability).
Related
I am making a program that can make an array from user input and save it inside a csv files. Then the user is able to perform matrix and vector operations with the stored arrays. When i started working with csv files(initially on clion) i started getting the error: "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)" After debugging i found the error "EXC_BAD_ACCESS (code=2, address=0x7ff7b202dff8)" . However the program still worked when ran in replit. Sadly though after i wrote lines 60 -65 in order to make a different csv file every time the function is ran i started getting the error: "signal: segmentation fault (core dumped) " on replit. What could be causing these errors? Here is my code on replit:
"https://replit.com/#iasonaszak/the-matrix#main.c"
Thank you in advance for your help!!
and here is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "time.h"
#include <math.h>
#include <stdbool.h>
int a;
char c[20];
int num;
bool b = true;
int main() {
while (b ==true){
void create_array();
void delete_array();
int user_answer;
time_t t;
srand((unsigned) time(&t));
printf(
" 1.create an array\n 2.load an array\n 3.Show available arrays\n 4.Delete array\n 5.Vector operations \n 6.Matrix operations"
) ;
printf("Please choose one of the following options!\n");
scanf("%d" , &user_answer);
if (user_answer == 1){
create_array( );
}
else if (user_answer == 4){
delete_array();
}
return 0;
}
}
void create_array(){
int rows;
int cols;
int i;
int j;
int matrix[i][j];
printf("how many columns would you like your array to have");
scanf("%d" ,&cols );
printf("how many rows would you like your array to have");
scanf("%d" ,&rows );
char filename[80];
FILE *fout = fopen(filename, "wt");
FILE *last = fopen("lastnum.csv" , "w");
fgets(c , 20 , last);
num = atoi(c);
snprintf(filename, sizeof(filename), "prefix.%d.csv", num);
for (i = 0 ; i < rows; i ++){
printf("\n");
fprintf(fout , "\n");
for (j = 0 ; j < cols; j ++){
scanf("%d", &matrix[i][j]);
char str[(int)((ceil(log10(matrix[i][j]))+1)*sizeof(char))];
sprintf(str , "%d " , matrix[i][j]);
fprintf(fout ,"%s" , str);
}
}
printf("Your array was saved successfuly inside a csv file");
num++;
}
void delete_array(){
remove("prefix.0.csv");
remove("prefix.1.csv");
remove("prefix.2.csv");
remove("prefix.3.csv");
remove("prefix.4.csv");
remove("prefix.5.csv");
remove("prefix.6.csv");
remove("prefix.7.csv");
remove("prefix.8.csv");
remove("prefix.9.csv");
printf("all arrays were deleted");
}
void preview_arrays(){
FILE *F0 = fopen("prefix.0.csv" , "r");
}
These three lines will cause a problem:
char str[(int)((ceil(log10(matrix[i][j]))+1)*sizeof(char))];
sprintf(str , "%d " , matrix[i][j]);
fprintf(fout ,"%s" , str);
The expression (int)((ceil(log10(matrix[i][j])) + 1 will produce 1 from a matrix value of 1, but char str[1]; won't be enough for the nul-terminated string.
And when the matrix value is <= 0 the logarithm is undefined. In my test with 0 it attempted to define char str[-2147483648];
You don't use str for anything else, so I suggest you remove those three lines and use this one simple line instead:
fprintf(fout,"%d ", matrix[i][j]);
Update
Another fault is in the file opening: wrong mode
FILE *last = fopen("lastnum.csv" , "w");
should be
FILE *last = fopen("lastnum.csv" , "r");
and always check that fopen() succeeds!
if(fout == NULL) {
/* handle error */
}
if(last == NULL) {
/* handle error */
}
and always check that fgets() succeeds too.
if(fgets(c , sizeof c , last)) == NULL) { // changed the 'magic' 20
/* handle error */
}
I am new to C and need some help, when I execute this code, the output shows "Floating point exception (core dumped)" instead of a number which I don't know what it could be. I don't really know what is wrong with my code since I am a total beginner with Linux and C. Every help is appreciated.
Here is my functions.c:
#include "header.h"
int count(FILE *file){
int count=0,n;
char word[WORDS];
while(fscanf(file,"%s",word)==1 ){
count++;
};
return count;
};
int total(FILE *file){
int numbers, sum=0;
int token;
while(token!=EOF){
token=fscanf(file,"%d",&numbers);
sum+=numbers;
};
return sum;
};
and here is my main.c:
#include "header.h"
int main(){
char word[WORDS];
char theFile[WORDS];
FILE *fileptr;
printf("Enter the file name: ");
scanf("%s",theFile);
printf("Reading file %s...\n", theFile);
fileptr=fopen(theFile,"r");
if(fileptr==NULL){
fprintf(stderr,"ERROR: The file '%s' does not exist\n", theFile);
return 1;
};
int theSum=total(fileptr);
int theCount=count(fileptr);
int theMean= theSum/theCount;
printf("Average weight: %d \n", theMean);
return 0;
};
The main reason for getting Floating point exception is that you are accessing the file beyond its size.
In function total and count you are using the same pointer, so when done with total the file pointer is at the end of file, and you are using the same in count also.
you need to do fseek(file,SEEK_SET,0);, to make the pointer point at the beginning.
and all of you block statements and functions are end by ;, thats wrong.
I have corrected the program as a whole assuming that the contents of the file are just numbers like this 1 2 3 4 5 6
#include <stdio.h>
#define WORDS 100
int count(FILE *file){
int count = 0,n;
char word[WORDS];
// you need this to access the elements from start of the file
// comment below line causes sigfpe, Floating point exception
fseek(file,SEEK_SET,0);
printf(" position of fptr in count = %d\n",ftell(file));
while(fscanf(file,"%s",word)==1 ){
count++;
}
return count;
}
int total( FILE *file ){
int numbers, sum = 0;
int token;
// This is checked after number is read, will add the last number 2 times
//while(token != EOF){
while(1)
{
token = fscanf(file,"%d",&numbers);
printf("N = %d, token = %d\n", numbers, token);
if(token == EOF )
break;
sum += numbers;
}
printf(" position of fptr in total at the end = %d, sum = %d\n",ftell(file), sum);
return sum;
}
int main(){
char word[WORDS];
char theFile[WORDS];
FILE *fileptr;
printf("Enter the file name: ");
scanf("%s",theFile);
printf("Reading file %s...\n", theFile);
fileptr=fopen(theFile,"r");
if(fileptr == NULL){
fprintf(stderr,"ERROR: The file '%s' does not exist\n", theFile);
return 1;
}
int theSum = total(fileptr);
int theCount = count(fileptr);
//make sure to add a check that `theCount` is not zero
int theMean = theSum/theCount;
printf("Average weight: %d \n", theMean);
return 0;
}
In this statement
int theMean= theSum/theCount;
when theCount is 0 you are dividing by zero, which is undefined behavior and is probably causing the FPE.
I'm working on a project that involves reading and /or writing from a text file. Currently the only data I'm attempting to extract from the text file are names. My goal is to be able to store specific names in a character pointer array such that Char[n] will have a name assigned to it for any given n in the array.
The problem I seem to be having is that I'm setting my character pointer element to another character array where I'm storing the read value from the text file.
For example, if I read a name from the text file and set Name[] equal to that name then later set Char[0] = Name then Char[0] will always change when Name does.
I've attempted to write the string directly to Char[0], for example, but then my program crashes just after I attempt to read and store the value. Therefore, I've resorted to this convoluted route of assigning a separate character array to the name I scan and setting one of my elements to it.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
FILE * inf = fopen("UserNames.txt", "r");
char User[125];
int err, TopNameNumber = 10;
char *UserNames[TopNameNumber];
if (inf == NULL)
{
printf("ERROR: No name file detected.");
return 0;
}
for(int i = 0; i < TopNameNumber i++)
{
//This reads from my .txt file
err = fscanf(inf, " %s", User);
if(err == EOF)
break;
//This shows me what user was read from the text file
printf("User read %d: %s\n", i+1, User);
//Program assigns the pointer address of User to Names[i]
//This is where I'm having trouble
UserNames[i] = User;
}
for(int c = 0; c < 3; c++)
{
// This always just prints out the last name read from the .txt file
for every name
printf("Name #%d: %s\n", c, UserNames[c]);
}
return 0;
}
I've been at this for a few days and I've found some interesting avenues which could possibly solve my problem, such as copying the string with strcpy() function, or perhaps casting User to something. All to no avail so far, however.
I would appreciate any advice as to what you think is the best solution to pursue if the solution isn't obvious here. I would like to avoid doing everything character by character, but I suppose I would be willing to in the long run.
I apologize for perhaps an unclear question, this is my first time asking one, and I'm just trying to give as much context as possible :)
My code compiles with no warnings or errors as of right now.
the blatant error I see is here:
//Program assigns the pointer address of User to Names[i]
//This is where I'm having trouble
UserNames[i] = User;
reusing the same buffer for all usernames isn't going to fly. On the other hand, you cannot use strcpy because no memory is allocated. You can use strdup which allocates & copies the string.
UserNames[i] = strdup(User);
or for the purists (since strdup isn't strictly in the standard):
UserNames[i] = malloc(strlen(User)+1);
strcpy(UserNames[i],User);
As a security side-note, since the buffer is 125 bytes long, I suggest limiting the input it can accept to 124+nul-termination:
err = fscanf(inf, " %124s", User);
Of course, you need to deallocate the strings when no longer used, or you'll get memory leaks if your program doesn't quit or is part of a bigger code.
free(UserNames[i]); // in a loop in the end, when no longer needed
You need to allocate memory for a separate char[] for each name you read from the file.
For example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
FILE *inf = fopen("UserNames.txt", "r");
if (inf == NULL) {
printf("ERROR: No name file detected.");
return 0;
}
int err, c = 0;
const int TopNameNumber = 10;
char UserNames[TopNameNumber][125];
for(int i = 0; i < TopNameNumber; i++) {
err = fscanf(inf, " %124s", UserNames[c]);
if (err == EOF)
break;
printf("User read %d: %s\n", c+1, UserNames[c]);
++c;
}
fclose(inf);
for(int i = 0; i < c; i++) {
printf("Name #%d: %s\n", i, UserNames[i]);
}
return 0;
}
Alternatively:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
FILE *inf = fopen("UserNames.txt", "r");
if (inf == NULL) {
printf("ERROR: No name file detected.");
return 0;
}
char User[125];
int err, c = 0;
const int TopNameNumber = 10;
char* UserNames[TopNameNumber];
for(int i = 0; i < TopNameNumber; i++) {
err = fscanf(inf, " %124s", User);
if (err == EOF)
break;
printf("User read %d: %s\n", c+1, User);
UserNames[c] = malloc(strlen(User) + 1);
if (UserNames[c] == NULL) {
printf("ERROR: Memory allocation failed.");
break;
}
strcpy(UserNames[c], User);
++c;
}
fclose(inf);
for(int i = 0; i < c; i++) {
printf("Name #%d: %s\n", i, UserNames[i]);
}
for(int i = 0; i < c; i++) {
free(UserNames[i]);
}
return 0;
}
I'm writing a c program to simulate FCFS scheduling algorithm. It will accept a command line argument as a file and calculate turnaround time and wait time for every process. However it can not read values from text file into variables successfully.
Here is the code
#include <stdio.h>
#define N 50
int main(int argc, char** argv)
{
int i = 0;
char line[20];
int n=0;
typedef struct
{
char name; //process name
int at; //arrive time
int pt; //process time
int ft; //finish time
int rt; //round time
int wt; //wait time
} Process;
Process pcs[N];
FILE* file = fopen( argv[1], "r");
while (fgets(line,sizeof(line),file) != NULL)
{
sscanf(line, "%s %d %d", pcs[i].name, pcs[i].at, pcs[i].pt);
line[strlen(line)-1] = '\0';
printf("%s %d %d\n",pcs[i].name, pcs[i].at, pcs[i].pt);
i++;
}
fclose(file);
pcs[0].ft=pcs[0].at+pcs[0].pt;
pcs[0].rt=pcs[0].ft-pcs[0].at;
pcs[0].wt=0;
for (n;n<4;n++)
{
if (pcs[n].at<pcs[n-1].ft)
{
pcs[n].ft=pcs[n-1].ft+pcs[n].pt;
pcs[n].rt=pcs[n].ft-pcs[n].at;
pcs[n].wt=pcs[n-1].ft-pcs[n].at;
}
else
{
pcs[n].ft=pcs[n].at+pcs[n].pt;
pcs[n].rt=pcs[n].ft-pcs[n].at;
pcs[n].wt=pcs[n-1].ft-pcs[n].at;
}
}
int x = 0;
for (x;x<n;x++)
{
printf("process name: %s", pcs[x].name);
printf("Turnaround Time: %d", pcs[x].rt);
printf("Wait Time: %d\n", pcs[x].wt);
}
return(0);
}
Here is the input file
And the output is
Thanks for any help and advice.
As pointed by alk, you're doing some mistakes:
In your struct declaration you have declared name as a single character, but in your file reading code(while loop containing fgets) you're passing %s which is for strings, so better change your declaration to a char name[SIZE] rather than char name. Bdw you should read the compiler warning and try to understand it, since that's what is creating problem.
You are supposed to pass address of variables in sscanf and it's variants, so change line 26 to:
sscanf(line, "%s %d %d", pcs[i].name, &pcs[i].at, &pcs[i].pt);
I've been racking my brain against this program for a couple months now. This was an assignment of a class I took last semester and while I passed, I could never make this one assignment work correctly (Seg Fault). I welcome any help or tips but I greatly appreciate explanations with answers to follow along.
This program is supposed to receive a filename that contains a list of filenames (240 for my example). Those files are located in a folder within the same directory as the list and the program. This program is supposed to take this list and parse it for 4 threads, splitting the filenames evenly for each thread (60 per thread for my example). Each thread then takes this list of 60 file names and opens each file one by one performing a WordCount function on each file. Once the threads complete their tasks, they are supposed to print the results for each file in order with each thread in its own block(i.e. Thread1 Results | Thread2 Results | Thread 3 Results, etc...).
I've debugged quite a bit and know that up until the threads are created everything works as it is supposed to. My problem seems to be during thread launch/execution. I've tried adding mutex to the mix but sadly it hasn't helped. I seem to be missing something or over thinking something as some of my class mates have shown me their much more compact code. Please assist. Thanks!
Here is the Main:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MaxLine 200
#define NUMTHREADS 4
char Line[MaxLine];
pthread_mutex_t Lock = PTHREAD_MUTEX_INITIALIZER;
typedef struct thread {
int id;
char file;
}ThreadData;
/* ThreadFunction will give each thread its processes to execute */
void *threadFunc (void *td) {
ThreadData *data = (ThreadData*)td;
int thread_num=data->id;
char filename=data->file;
printf("thread debug tid: %d and file: %c",thread_num, filename);
pthread_mutex_trylock(&Lock);
FILE *fn = fopen(filename, "r");
if (fn == NULL) {
error("ERROR: Opening file");
return 1;
}
while (fgets(Line, sizeof(Line), fn) != NULL) {
CountWord(thread_num, Line);
}
fclose(fn);
free(data);
pthread_mutex_unlock(&Lock);
pthread_exit(NULL);
}
int main(int argc, char *argv[]){
char buf[20];
int c, i, t, tnum, QUEUETOTAL;
pthread_t thread[NUMTHREADS];
ThreadData td[NUMTHREADS];
if (argc != 2){
fprintf(stderr,"ERROR: Usage must be Countfile filename\n", argv[0]);
exit(0);
}
char const* const filename = argv[1];
FILE* file = fopen(filename, "r");
if ( file == 0 ){
printf( "Could not open file!\n" );
exit(0);
}
/* Count iterations of while loop to divide files among threads. */
while (fgets(Line, sizeof(Line), file)){
QUEUETOTAL++;
}
/* Divide work for threads. */
int thread2taskstart=(QUEUETOTAL/NUMTHREADS); //60
int thread3taskstart=(QUEUETOTAL/NUMTHREADS)*2; //120
int thread4taskstart=(QUEUETOTAL/NUMTHREADS)*3; //180
// QUEUETOTAL = 240
rewind(file);
FILE *tempfile1 = fopen("temp1.txt","w");
for (i=0; i<thread2taskstart; i++) {
// populate tempfile1 with entries 1-60
if(fgets(Line,sizeof(Line),file)!=NULL) {
fputs(Line,tempfile1);
//printf("Debug temp1: %s",Line);
}
}
fclose(tempfile1);
FILE *tempfile2 = fopen("temp2.txt","w");
for (i=thread2taskstart; i<thread3taskstart; i++) {
// populate tempfile2 with entries 60-120
if(fgets(Line,sizeof(Line),file)!=NULL) {
fputs(Line,tempfile2);
//printf("Debug temp2: %s",Line);
}
}
fclose(tempfile2);
FILE *tempfile3 = fopen("temp3.txt","w");
for (i=thread3taskstart; i<thread4taskstart; i++) {
// populate tempfile3 with entries 120-180
if(fgets(Line,sizeof(Line),file)!=NULL) {
fputs(Line,tempfile3);
//printf("Debug temp3: %s",Line);
}
}
fclose(tempfile3);
FILE *tempfile4 = fopen("temp4.txt","w");
for (i=thread4taskstart; i<=QUEUETOTAL; i++) {
// populate tempfile3 with entries 180-240
if(fgets(Line,sizeof(Line),file)!=NULL) {
fputs(Line,tempfile4);
//printf("Debug temp4: %s",Line);
}
}
fclose(tempfile4);
fclose(file);
/* Prepare parameters & launch (4) threads. Wait for threads
to finish & print out results as specified in assignment. */
printf("Counting files …\n");
for(t=0;t<NUMTHREADS;t++){
tnum=t+1;
snprintf(buf, "temp%d.txt", tnum);
printf("debug tnum and array: %d and %s\n",tnum, buf);
td[t].id = tnum;
td[t].file = buf;
// Creates a new thread for each temp file.
pthread_create(&thread[t], NULL, threadFunc, td);
}
// Joins threads.
printf("debug: printing threads \n");
for(t=0;t<NUMTHREADS;t++){
pthread_join(thread[t], NULL);
printf("------------------------- Processes finished for Thread %d ----------------------- \n",t+1);
}
return 0;
}
Here is the Count Function:
#include <stdio.h>
int CountWord(int tinfo, char cfile){
int i;
int ccount = 0;
int wcount = 0;
int lcount = 0;
FILE *fname;
char fn[strlen(cfile) + 18];
sprintf(fn, "./CountingFolder/%s", cfile);
printf("Debug: %s\n", fn);
fname = fopen(fn, "r");
if (fname == NULL) {
error("ERROR: Opening file");
}
while ((i = fgetc(fname)) != EOF){
if (i == '\n') {
lcount++;
}
if (i == '\t' || i == ' '){
wcount++;
}
ccount++;
}
printf("Threadid %d processes %s which has %d characters, %d words and %d lines\n", tinfo, cfile, ccount, wcount, lcount);
fclose(fname);
return 0;
}
1) Probably a typo. But
int CountWord(int tinfo, char cfile){ .. }
should be
int CountWord(int tinfo, char *cfile){ .. }
2) You are passing the same buf to all threads from main(). Data race and undefined behaviour.
3) None of the snprintf() calls take the size argument. Undefined behaviour.
4) Since all threads work on different data, you don't need a lock at all.
5) You didn't allocate td array. So you can't call free(data); in the thread function. Undefined behaviour.
There may be more issues with the code but the segfault is likely because of (3) or (5).
In your code here
snprintf(buf, "temp%d.txt", tnum);
printf("debug tnum and array: %d and %s\n",tnum, buf);
td[t].id = tnum;
td[t].file = buf;
the last line assigns a pointer into the file field of this struct
typedef struct thread {
int id;
char file;
}ThreadData;
Shouldn't it be char *file; ? I don't have thread.h in MSVC so I can't compile it. Surely you have all warnings enabled??