I've been trying to split writing to a file with threads and to do so I'm trying to use structs to hold the start and end positions of the file. The code compiles, However, I've been getting a segmentation fault when the code tries to create multiple threads and doesn't execute the thread code. Am I using structs correctly?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define MAX_THREADS 100
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
struct position {
int start;
int end;
};
void *ThreadJob(void *id) //what the thread should do
{
pthread_mutex_lock(&mutex);
struct position *b;
printf("\nstart: %d \nend: %d\n", (*b).start, (*b).end);
double* arrayPtr = malloc( 100000* sizeof(double));
FILE *file;
FILE* nFile; // New file
double n;
nFile = fopen("newTriData1.txt","a");
char line[128]; //the lines of the txt file
file = fopen("TriData1.txt", "r");
long tid;
tid = (long)id;
int count = 0;
while (fgets(line, 128, file)) //gets the lines from the txt file - line by line
{
sscanf(line ," %lf", &arrayPtr[count]); //converts the value on the line into a double to manipulate
count++; //increment the count
}
free(arrayPtr);
while((*b).start<(*b).end){
double x = (sqrt(8*arrayPtr[(*b).start]+1) - 1) / 2; //equation to detect triangular numbers
if (x == floor(x)) //checks if the value has a remainder. The value should be a whole number
{
fprintf(nFile, "\nNumber %s: Triangular\n", line); //if true writes the value and triangular
}
else
{
fprintf(nFile, "\nNumber %s: Not Triangular\n", line);
}
(*b).start++;
}
(*b).start=(*b).end;
(*b).end = ((*b).end + (*b).end);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main (void) //main
{
struct position a;
(a).start=0;
int line_count;
FILE *file;
double count_lines = 1.0;
char check;
double i = 4;
file = fopen("TriData1.txt", "r");
double divider;
check = getc(file);
while (check != EOF)
{
if (check == '\n')
{
count_lines = count_lines + 1;
}
check = getc(file); //take the next character from the file
}
printf("cl: %f", count_lines);
double vo = fmod(count_lines,4); //using fmod to find which number divides the line count into equal parts for the number of threads
if (fmod(count_lines,4) == 0) {
double value1 = count_lines/4;
double value2 = count_lines/4;
double value3 = count_lines/4;
double value4 = count_lines/4;
printf("v1: %f \n v2: %f \n v3: %f \n v4: %f", value1,value2,value3,value4);
divider =4;
line_count = count_lines/4;
(a).end=line_count;
}
else
{
while (fmod(count_lines, i) != 0) //if the value is not divisible by 4 then i will increment until a suitable divider is found
{
i++;
divider = i;
line_count = count_lines/i;
printf("divider: %f", divider);
}
(a).end=line_count;
}
fclose(file); //close file.
printf("There are %f lines in this file\n", count_lines);
printf("\nstart: %d \nend: %d\n", (a).start, (a).end);
pthread_t threads[MAX_THREADS];
int thread;
long threadNum ;
for(threadNum=0; threadNum<divider; threadNum++){
printf("Creating thread %ld\n", threadNum);
thread = pthread_create(&threads[threadNum], NULL, ThreadJob, (void *)threadNum);
if (thread){
printf("ERROR; %d\n", thread);
exit(-1);
}
}
pthread_exit(NULL);
return 0;
}
Almost every line of your code is wrong, but most of your mistakes will just make your program do the wrong thing, not crash entirely. Here's just the mistakes that are making your program crash:
struct position *b;
printf("\nstart: %d \nend: %d\n", (*b).start, (*b).end);
That will probably segfault because you can't dereference an uninitialized pointer.
free(arrayPtr);
while((*b).start<(*b).end){
double x = (sqrt(8*arrayPtr[(*b).start]+1) - 1) / 2; //equation to detect triangular numbers
That might segfault because you can't use memory after you free it. Also, the last line of it will probably segfault because you still never initialized b.
(*b).start++;
}
(*b).start=(*b).end;
(*b).end = ((*b).end + (*b).end);
All of those lines will probably segfault because b still isn't initialized.
Frankly, you should give up on advanced topics like threads for now and work on trying to understand the basics of C.
Related
In file I need to read some inputs:
this is an example:
8 15
[1,1] v=5 s=4#o
[4,2] v=1 s=9#x
typedef struct{
int red2;
int stupac2;
int visina;
int sirina;
char boja[10];
}Tunel;
FILE* fin = fopen("farbanje.txt", "r");
Tunel* tuneli = malloc(sizeof(Tunel)*50);
// if(fin!=0)
fscanf(fin,"%d %d", &r,&s);
printf("%d %d", r,s);
int p=0;
while (fscanf(fin, "[%d,%d]", &tuneli[p].red2, &tuneli[p].stupac2) == 2)
{
p++;
}
for(i=0;i<p;i++)
{
printf("[%d,%d]", tuneli[i].red2, tuneli[i].stupac2);
}
Problem is that it wont read me properly inputs from here: [1,1] v=5 s=4#o
Last line where i use printf shows some random numbers.
Agree it is better to use fgets
But if you want to continue to use your current approach,
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int red2;
int stupac2;
int visina;
int sirina;
char boja[10];
}Tunel;
int main(){
int r, s, i;
FILE*fin=fopen("farbanje.txt", "r");
if(fin==NULL) {
printf("error reading file\n");
return 1;
}
Tunel *tuneli=(Tunel*)malloc(sizeof(Tunel)*50);
fscanf(fin,"%d %d\n", &r,&s);
printf("%d %d", r,s);
int p=0;
while (fscanf(fin, " [%d,%d]%*[^\n]", &tuneli[p].red2, &tuneli[p].stupac2) == 2)
{
p++;
}
fclose(fin);
for(i=0;i<p;i++)
{
printf("[%d,%d]", tuneli[i].red2, tuneli[i].stupac2);
}
}
Last line where i use printf shows some random numbers....
The random numbers you see are because the buffers to print were not properly populated yet.
This example shows how to read the file, using fgets() to read a line buffer, then use sscanf() to parse the first two values from the lines. (read in-code comments for a few other tips.)
int main(void)//minimum signature for main includes 'void'
{
int r = 0;
int s = 0;
char line[80] = {0};//{initializer for arrays}
int p = 0;
Tunel *tuneli = malloc(sizeof(*tuneli)*50);
if(tuneli)//always test return of malloc before using it
{
FILE *fin = fopen(".\\farbanje.txt", "r");
if(fin)//always test return of fopen before using it
{
fgets(line, sizeof(line), fin);
sscanf(line, "%d %d", &r, &s);
while(fgets(line, sizeof(line), fin))
{
sscanf(line, " [%d,%d]", &tuneli[p].red2, &tuneli[p].stupac2);
//note space ^ here to read only visible characters
printf("[%d,%d]\n", tuneli[p].red2, tuneli[p].stupac2);//content is now populated corretly
p++;
}
fclose(fin);//close when finished
}
free(tuneli);//free when done to prevent memory leaks
}
return 0;
}
I have a program that must take on command-line a file_name, a string string_name (word) and an integer (number of threads) as arguments. Then the program creates those many threads to count the number of times string_name occurs in the file - file_name.
The serial code run properly.
The multithreaded code has following problems:
It leads to core dump - segmentation fault.
It is giving wrong count.
I added some debugging statements:
It is showing wrong line numbers where I am trying to print which line number is being checked by which thread number.
#include <stdio.h>
// #include <conio.h> - Does not exist in gcc
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#define MAX_LINE_LENGTH 4096
#define MAX_WORD_SIZE 64
#define MAX_THREAD_COUNT_PER_PROCESS 64
// Important - in GCC - for pthread functions in addition to include pthread.h must also use flag -lpthread in compilation command
// gcc -w -o main main_multithreaded.c -lpthread
typedef unsigned int uint;
typedef struct {
uint valid;
uint line_num;
char* line;
} struct_line;
volatile struct_line buffer[MAX_THREAD_COUNT_PER_PROCESS];
pthread_mutex_t *buffer_mutex;
pthread_t* threads;
typedef struct {
FILE* fp;
} read_pthread_argv_type;
read_pthread_argv_type read_pthread_argv;
void read_file(void* read_pthread_argv)
{
read_pthread_argv_type* i_read_pthread_argv;
i_read_pthread_argv = (read_pthread_argv_type*) read_pthread_argv;
FILE* local_file_ptr;
local_file_ptr = i_read_pthread_argv->fp;
char *line;
uint i, line_count = 0, line_length;
line = (char*) malloc (MAX_LINE_LENGTH);
while (fgets(line, MAX_LINE_LENGTH, local_file_ptr) != NULL)
{
line_length = strlen (line);
while (pthread_mutex_lock(buffer_mutex))
{}
for (i = 0; i<MAX_THREAD_COUNT_PER_PROCESS; i++)
{
if (buffer[i].valid != 1)
{
break;
}
}
buffer[i].line = (char*) malloc (line_length);
buffer[i].line = line;
buffer[i].line_num = line_count;
buffer[i].valid = 1;
// printf ("Line %u of file read and saved as %s \n", buffer[i].line_num, buffer[i].line);
line_count++;
pthread_mutex_unlock(buffer_mutex);
}
printf ("File read finished \n");
free (line);
pthread_exit(NULL);
}
typedef struct {
char* string_to_search;
uint thread_num;
uint count;
} count_pthread_argv_type;
count_pthread_argv_type count_pthread_argv[MAX_THREAD_COUNT_PER_PROCESS];
int count_string (void* pthread_argv_i)
{
// Declare variables for line and word
char *line, *word;
line = (char*) malloc (MAX_LINE_LENGTH);
word = (char*) malloc (MAX_WORD_SIZE);
// Declare and initiaize count
uint count = 0, wordcount_in_line;
uint i, k = 0;
int j;
count_pthread_argv_type* i_pthread_argv;
i_pthread_argv = (count_pthread_argv_type*)pthread_argv_i;
char* local_string_to_search = i_pthread_argv->string_to_search;
uint local_thread_num = i_pthread_argv-> thread_num;
//printf (" For thread %u -> Local string to search = %s \n starting line = %u and num_lines = %u \n", \
local_thread_num, local_string_to_search, local_starting_line, local_num_lines);
//getchar();
while (1)
{
while (pthread_mutex_lock(buffer_mutex))
{}
for (i=0; i < MAX_THREAD_COUNT_PER_PROCESS; i++)
{
if (buffer[i].valid == 1)
{
line = buffer[i].line;
k = buffer[i].line_num;
buffer[i].valid = 0;
printf ("Thread %u checking line %u - which is %s \n", local_thread_num, k, buffer[i].line);
break;
}
}
pthread_mutex_unlock(buffer_mutex);
i = 0, j = 0, wordcount_in_line = 0;
while ( (*(line+i) != '\n') )
{
// Extract word
if ( (*(line+i) == ' '))
{
// NUll terminate the word to make it a string
*(word+j) = '\0';
// Compare
//printf ("Thread %u checking line %u - word number %u which is %s \n", local_thread_num, k, wordcount_in_line, word);
if (strcmp (word, local_string_to_search) == 0) // No double quotes around argv[2]
{
count ++;
printf("Thread %u found its local %uth occurence of %s in line %u at word %u \n", local_thread_num, count, word, k, wordcount_in_line);
}
// Make j = -1, after increment it will be 0 for new word
j = -1;
wordcount_in_line++ ;
}
else
{
*(word+j) = *(line+i);
}
// Increment both i and j to go to next character
i++; j++;
}
if ((*(line + i)) == '\n')
{
// If end of line - do the same thing on last word as is for every word
// NUll terminate the word to make it a string
*(word + j) = '\0';
// Compare
//printf ("Thread %u checking line %u - word number %u which is %s \n", local_thread_num, k, wordcount_in_line, word);
if (strcmp(word, local_string_to_search) == 0) // No double quotes around argv[2]
{
count++;
printf("Thread %u found its local %uth occurence of %s in line %u at word %u \n", local_thread_num, count, word, k, wordcount_in_line);
}
wordcount_in_line++ ;
}
}
void* status;
int rc;
rc = pthread_join (threads[0], &status);
printf ("Thread %u found %u occurences \n", local_thread_num, count);
i_pthread_argv->count = count;
//return (count);
pthread_exit(NULL);
}
int main (int argc, char* argv[])
{
// Declare file *
FILE* fp;
// Get file path and open file
//fp = fopen ("file_name.txt","r");
fp = fopen (argv[1],"r"); // No "" around argv[1]
if (fp == NULL)
{
printf ("fopen failed \n");
return 0;
}
printf ("file = %s and string to look for = %s \n", argv[1], argv[2]);
//fopen_s(&fp, "file_name.txt", "r");
//Initialize mutex
if (pthread_mutex_init(buffer_mutex, NULL))
printf ("Mutex initialization failed \n");
// Get number of lines in file
uint num_threads;
sscanf(argv[3], "%u", &num_threads);
// Create threads
//pthread_t* threads;
threads = (pthread_t*) malloc (sizeof (pthread_t)*MAX_THREAD_COUNT_PER_PROCESS);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
uint i = 0;
read_pthread_argv.fp = fp;
if ( pthread_create (&threads[0], &attr , read_file, (void*)(&read_pthread_argv) ) == 0)
printf("Thread creation %u passed \n", i);
for ( i = 1; i<num_threads; i++ )
{
count_pthread_argv[i].thread_num = i;
count_pthread_argv[i].string_to_search = argv[2];
//printf("Reached debugging point 1 \n");
if ( pthread_create (&threads[i], &attr , count_string, (void*)(&count_pthread_argv[i]) ) == 0)
printf("Thread creation %u passed \n", i);
}
//printf("Reached debugging point 2 \n");
// Doubt 2 - How to call pthread_join to wait for completion of multiple threads -
// Isnt the for loop executed sequentially and pthread_join in main for thread-2 will be executed after thread-1 exits
// Wait till all are over
pthread_attr_destroy(&attr);
void* status;
int rc;
for (i = 1; i<num_threads; i++ )
{
rc = pthread_join (threads[i], &status);
}
uint totalcount = 0;
for (i = 1; i<num_threads; i++)
{
printf ("count_returned = %u \n", count_pthread_argv[i].count);
totalcount += count_pthread_argv[i].count;
}
printf("From main, The file has %s -> %u times", argv[2], totalcount);
for (i=0; i<MAX_THREAD_COUNT_PER_PROCESS; i++)
{
free (buffer[i].line);
}
pthread_mutex_destroy(buffer_mutex);
getchar();
pthread_exit(NULL);
}
hope some experts can help me. It's my first time posting on Stack so please be patient with me. Thanks.
Here are a list of my problems:
Tried to open a text file from argv[1] but the program showed NULL
Tried to use fgetc to read in one character at a time. When hit "white_space", put ('2.2') in a buff, add a '\0', then use sscanf to turn it into a double type. Not sure if this approach is right.
Here is my code:
/*
* This program computes simple statistics from a file of ASCII numbers
*/
/*
* File: statsMain.c
* Author: William Vu T Nguyen
* ID: C0436847
* Created on February 6, 2017, 12:10 PM
*/
#include "statistics.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void printStats(FILE *dest, const int count, const double mean,
const double ssdev);
// main program
int main(int argc, char** argv) {
FILE *pFile;
int count;
int x;
char buff[100] = {0};
char *pBuff = buff;
double numVal;
double sum;
double sumsq;
double calculatedMean;
double calculatedStdDev;
if (argc != 2) {
fprintf(stderr, "usage: %s dataFileName\n", argv[0]);
exit(EXIT_FAILURE);
} else {
if ((pFile = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "Unable to open input file \"%s\"\n", argv[1]);
exit(EXIT_FAILURE);
} else {
while ((x = fgetc(pFile)) != EOF) {
*pBuff = x;
sscanf(pBuff, "%lf", &numVal);
sum += numVal;
sumsq += (sum * sum);
count++;
pBuff++;
}
calculatedMean = mean(sum, count);
calculatedStdDev = ssdev(sum, sumsq, count);
printStats(pFile, count, calculatedMean, calculatedStdDev);
}
fclose(pFile);
}
return (EXIT_SUCCESS);
}
void printStats(FILE *dest, const int count, const double mean,
const double ssdev) {
char str[100] = {0};
sprintf(str, "%d Values, Mean = %lf, Sample Standard Deviation = %lf"
, count, mean, ssdev); //deal with buffer
puts(str);
fprintf(dest, "%s", str);
}
If my code shows that I'm a novice in C then please be patient as I'm still in my learning stage. I love programming, circuit design, and microcontroller. Did horribly in school when learning those subjects but I never let it be a determined factor of my life. Thanks.
You're also:
passing pFile which was opened as read only, and trying to write to it
using sum, sumsq, and count without initializing them
probably making a mistake with sumsq += (sum * sum);
It's better to take advantage of inherent stdin and stdout file pointers, then you can do stuff like:
stats < input_file > output_file
Where stats is your program. If you're using Linux, you can chain your program to tee and do exactly what you're trying to do (i.e. output to console and file) but with no extra code.
How I would write it:
#include <stdlib.h>
#include <stdio.h>
#include "statistics.h"
void printStats(const int count, const double mean, const double ssdev);
int main() {
int count = 0;
double numVal, sum = 0.0, sumsq = 0.0;
double calculatedMean, calculatedStdDev;
while (scanf("%lf", &numVal)) {
sum += numVal;
sumsq += numVal * numVal;
count++;
}
calculatedMean = mean(sum, count);
calculatedStdDev = ssdev(sum, sumsq, count);
printStats(count, calculatedMean, calculatedStdDev);
return EXIT_SUCCESS;
}
void printStats(const int count, const double mean, const double ssdev) {
printf("%d Values, Mean = %lf, Sample Standard Deviation = %lf\n",
count, mean, ssdev);
}
I'm using qsort to sort an array of i strings of size 256, such as char *arr = malloc(i * 256) -- was actully done with reallocs inside a loop. Each string contains, among text, a number, which I use as the comparison element:
int
cmp(const void *a, const void *b)
{
double atime = get_time((char*)a);
double btime = get_time((char*)b);
return (atime > btime) - (atime < btime);
}
When i is small, it works. With a large i, it fails to sort the array correctly. get_time is working. I was using it with a custom heapsort implementation before, which worked flawlessly.
I added the following to cmp to check what was happening:
fprintf(stderr, "Comparing %f to %f, result: %d.\n", atime, btime, (atime > btime) - (atime < btime));
It seems that all comparisons are correct, but not all comparisons are being made. arr has several strings containing 1.something, however I couldn't find any comparison between numbers greater than 1 in the output. The call to qsort is as follows:
qsort((void*)arr, i-1, MAX_ROW_LEN, cmp);
It's the same parameters I used to pass to my heapsort function, but it doesn't work.
Complete code, and example file (fails to sort).
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define MAX_ROW_LEN 256
#define MAX_FILENAME_LEN 256
/* Return the start time of the event or -1 if no time. */
static double
get_time(const char *event)
{
if (!event || event[0] == '%')
return -1;
size_t tok = strcspn(event, " ") + 2;
double ans = strtod(event + tok, NULL);
if (!ans)
return -1;
return ans;
}
/*static inline*/ int
cmp(const void *a, const void *b)
{
double atime = get_time((char*)a);
double btime = get_time((char*)b);
return (atime > btime) - (atime < btime);
}
int
main(int argc, char **argv)
{
/* process parameters */
if (argc < 2) {
fprintf(stderr, "Supply a file to sort.\n");
exit(EXIT_FAILURE);
}
if (strlen(argv[1]) > MAX_FILENAME_LEN) {
fprintf(stderr, "Filename too long.\n");
exit(EXIT_FAILURE);
}
/* read the file */
printf("Now processing %s.\n", argv[1]);
FILE *f = fopen(argv[1], "r");
if (!f) {
fprintf(stderr, "Failed to open out. Errno %d.\n", errno);
exit(EXIT_FAILURE);
}
char *trace = malloc(MAX_ROW_LEN);
char *header = malloc(MAX_ROW_LEN);
size_t i = 1, j = 1;
while (fgets(trace + (i-1)*MAX_ROW_LEN, MAX_ROW_LEN, f)) {
/* (if we can't get the time, it's part of the header) */
if (get_time(trace + (i-1)*MAX_ROW_LEN) != -1) {
trace = realloc((void*)trace, (++i)*MAX_ROW_LEN);
} else {
strncpy(header + (j-1)*MAX_ROW_LEN, trace + (i-1)*MAX_ROW_LEN,
MAX_ROW_LEN);
header = realloc((void*)header, (++j)*MAX_ROW_LEN);
}
}
if (!feof(f)) {
fprintf(stderr, "Error reading file. Errno %d.\n", ferror(f));
exit(EXIT_FAILURE);
}
printf("Read %zu lines.\n", i);
fclose(f);
/* write the header */
f = fopen("out_fixed", "w");
if (!f) {
fprintf(stderr, "Failed to open out_fixed. Errno %d.\n", errno);
exit(EXIT_FAILURE);
}
for (size_t k = 0; k < j-1; ++k) {
/* (there is '%' in comments, can't print formatted) */
fputs((void*)(header + k*MAX_ROW_LEN), f);
}
/* sort */
printf("Started sorting.\n");
time_t start = time(NULL);
qsort((void*)trace, i-1, MAX_ROW_LEN, cmp);
printf("Ended sorting, took %fs.\n", difftime(time(NULL), start));
/* write the sorted trace */
printf("Started writting to disk.\n");
start = time(NULL);
for (size_t k = 0; k < i-1; ++k) {
fprintf(f, "%s", trace + k*MAX_ROW_LEN);
}
printf("Took %fs.\n", difftime(time(NULL), start));
/* flush */
printf("Closing file (fflush)\n");
start = time(NULL);
if (fclose(f)) {
fprintf(stderr, "Failed to close out_fixed. Errno %d.\n", errno);
exit(EXIT_FAILURE);
}
printf("Took %fs.\n", difftime(time(NULL), start));
exit(EXIT_SUCCESS);
}
I've tested your code and your example input file and it seems to work fine. In your question you say:
... has several strings containing 1.something, however I couldn't find
any comparison between numbers greater than 1 in the output.
But there are no such lines in your example input file.
Given this example line of your input:
12 0.475183170 rank3 STATE fill_row
This line in get_time is going to skip over any leading digits in your double:
size_t tok = strcspn(event, " ") + 2;
strcspn returns the number of characters that it had to read before finding the "needle" so in this case it will return 2. You then add 2 to that and then use that as a pointer offset into your event string, meaning that you are passing a pointer to .475183170 instead of 0.475183170.
You'd be better off just using strchr here anyway:
char *tok = strchr(event, ' ');
if (!tok) {
return -1;
}
double ans = strtod(tok, NULL);
The subsequent strtod will skip leading whitespace for you, so you don't need to get super fancy.
I am trying to write a program to compile with Xeon Phi and it says there is a segmentation fault? I think it is when I try to fill the arrays with the getc function. I have written this code several different formats, and I understand that this might not be the most efficient, but I need to test it out to see if it will work by parallelizing it
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include <omp.h>
int main()
{
struct stat buf1;
struct stat buf2;
FILE *fp1, *fp2;
int ch1, ch2;
clock_t elapsed;
char fname1[40], fname2[40];
printf("Enter name of first file:");
fgets(fname1, 40, stdin);
while (fname1[strlen(fname1) - 1] == '\n')
{
fname1[strlen(fname1) -1] = '\0';
}
printf("Enter name of second file:");
fgets(fname2, 40, stdin);
while (fname2[strlen(fname2) - 1] == '\n')
{
fname2[strlen(fname2) -1] = '\0';
}
fp1 = fopen(fname1, "rb");
if (fp1 == NULL)
{
printf("Cannot open %s for reading\n", fname1);
exit(1);
}
fp2 = fopen(fname2, "rb");
if (fp2 == NULL)
{
printf("Cannot open %s for reading\n", fname2);
exit(1);
}
stat(fname1, &buf1);
size_t size1 = buf1.st_size;
stat(fname2, &buf2);
size_t size2 = buf2.st_size;
printf("Size of file 1: %zd\n", size1);
printf("Size of file 2: %zd\n", size2);
elapsed = clock(); // get starting time
size_t smallest = 0;
if(size1 < size2)
{
smallest = size1;
}
else
{
smallest = size2;
}
printf("Smallest Value: %zu\n", smallest);
size_t i, j, k;
size_t data[smallest];
size_t arry1[smallest];
size_t arry2[smallest];
unsigned long long counter = 0;
for(i = 0; i < smallest; i++)
{
data[i] = 1;
arry1[i] = getc(fp1);
arry2[i] = getc(fp2);
}
//#pragma omp for //reduction(+:counter)
for(k = 0; k < smallest; k++)
{
if((arry1[k] ^ arry2[k]) == 0)
{
counter+= data[k];
}
}
fclose (fp1); // close files
fclose (fp2);
float percent = (float)counter / (float)smallest * 100.0f;
printf("Counter: %zu Total: %zu\n", counter, smallest);
printf("Percentage: %.2f%\n", percent);
elapsed = clock() - elapsed; // elapsed time
printf("That took %.2f seconds.\n", (float)elapsed/CLOCKS_PER_SEC);
return 0;
}
Thanks for your help in advance!
You cannot declare an array with a size that's not known at compile time:
int smallest;
smallest = .... // some computation
size_t data[smallest]; // this is wrong!
You should instead use malloc() to accomplish that:
size_t *data;
smallest = ... // whatever
data = malloc(smallest * sizeof(size_t));
This loop:
while (fname1[strlen(fname1) - 1] == '\n')
fname1[strlen(fname1) -1] = '\0';
will read off the start of the string if the line was blank (i.e. "\n"). Change while to if.
Also, check that smallest > 0 before declaring the VLAs.
It might be insightful to output the value of smallest, typical systems default to a stack size of somewhere between 1MB and 8MB, so perhaps you cause a stack overflow here. You could eliminate this possibility by using malloc, as ocho88 suggests (but without the bogus cast):
size_t *data = malloc(smallest * sizeof *data);
size_t *arry1 = malloc(smallest * sizeof *arry1);
size_t *arry2 = malloc(smallest * sizeof *arry2);
if ( !data || !arry1 || !arry2 )
// exit with out-of-memory error
I'm not sure why you use a size_t to store the result of getc.
If this does not solve the problem then it would be useful to identify which line is segfaulting. If you can't get a debugger working, then you can output (to stderr, or to stdout with fflush) to find out where it is getting up to.