Seg Fault when using pthread_create - c

I am having difficulty creating thread when using pthread_create, I have tried changing functions to void* and such but it keeps throwing a segmentation fault.
Any help towards fixing this problem would be appreciated, I have tried researching this problem but to no avail I have yet to find a solution
Here is my code below:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <getopt.h>
#include <stdbool.h>
void readSudoku(int x[][9], FILE *in);
void printSudoku(int x[][9]);
int validateRows(int x[9][9]);
int validateCols(int x[9][9]);
int validateSubGrids(int x[9][9]);
void *vr(int x[9][9]);
void *vc(int x[9][9]);
void *vs(int x[9][9]);
bool validSudokuGrid(int x[][9]);
/* These are the only two global variables allowed in your program */
static int verbose = 0;
static int use_fork = 0;
// This is a simple function to parse the --fork argument.
// It also supports --verbose, -v
void parse_args(int argc, char *argv[])
{
int c;
while (1)
{
static struct option long_options[] =
{
{"verbose", no_argument, 0, 'v'},
{"fork", no_argument, 0, 'f'},
{0, 0, 0, 0}};
int option_index = 0;
c = getopt_long(argc, argv, "vf", long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 'f':
use_fork = 1;
break;
case 'v':
verbose = 1;
break;
default:
exit(1);
}
}
}
int main(int argc, char *argv[])
{
// Commented this out because this will be used later
// parse_args(argc, argv);
// if (verbose && use_fork) {
// printf("We are forking child processes as workers.\n");
// } else if (verbose) {
// printf("We are using worker threads.\n");
// }
// printf("Test");
// Initializing sudoku grid to parse file grid
int sudoku_grid[9][9];
if (argc == 1)
{
printf("File successfully opened!\n");
}
readSudoku(sudoku_grid, stdin);
printSudoku(sudoku_grid);
// validateRows(sudoku_grid);
// validateCols(sudoku_grid);
if (validSudokuGrid(sudoku_grid))
{
printf("The input is a valid Sudoku. \n");
}
else
{
printf("The input is not a valid Sudoku. \n");
}
return 0;
}
void readSudoku(int x[][9], FILE *in)
{
fseek(in, -1, SEEK_CUR); // Seek to start off the current position of the file ptr
char entry;
int i, j, totalVals = 0;
while ((fread(&entry, 1, 1, in)) > 0 && totalVals < 81)
{ // Read 81 digits from stdin file
if (entry != '\n')
{ // Ignore newline
if (isdigit(entry))
{
++totalVals;
x[i][j] = entry - '0'; // Store integer representation
++j;
if (j == 9)
{
j = 0;
++i;
}
}
}
}
}
void printSudoku(int x[][9])
{
int i = 0, j = 0; // i = rows, j = cols
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
// if we are on the third or fifth number of sub-grid
// we make a space between nums
if (2 == j || 5 == j)
{
printf("%d ", x[i][j]);
}
// if we are on the last num of row we make a space
else if (8 == j)
{
printf("%d\n", x[i][j]);
}
// anything else we make a space
else
{
printf("%d ", x[i][j]);
}
}
// if we are on row 3 or row 5 we make a space
if (2 == i || 5 == i)
{
printf("\n");
}
}
}
// Used to validate rows per 3x3 grid
int validateRows(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
// Validating columns in the 3x3 grid *BACK UP*
// Fixing column tracking
// int validateCols(int x[9][9]) {
// int col = 0;
// // Traversing Rows
// for(int i = 0; i < 9; i++) {
// // Initialzing array to detect for duplicate values
// int colValidate[9] = {0};
// // Traversing columns
// for(int j = 0; j < 9; j++) {
// // Holds current value depending on row / col
// int currVal = x[i][j];
// // If the index is filled with a zero
// // that means the index is not taken
// if(colValidate[currVal - 1] == 0) {
// colValidate[currVal - 1] = 1; // fill index with 1 (true)
// } else { // Checks if dupllicate or out of bounds
// printf("Column: %d does not have the required values\n", j + 1);
// return 0;
// }
// } col ++;
// }
// }
// Function to check 3x3 Sub-Grids
int validateCols(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
// Needs intense fixing
int validateSubGrids(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The top left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("The top mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("The top right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("The left mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("The left right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The bottom left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("The bottom mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("The bottom right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
void *vr(int x[9][9]) {
validateRows(x);
}
void *vc(int x[9][9]) {
validateCols(x);
}
void *vs(int x[9][9]) {
validateSubGrids(x);
}
bool validSudokuGrid(int x[][9])
{
int numThreads = 2;
pthread_t tid [2];
for(int i = 0; i < 1; i++) {
if(i == 0) {
pthread_create(&tid[i], NULL, vr(x), NULL);
} else if(i == 1) {
pthread_create(&tid[i], NULL, vc(x), NULL);
} else {
pthread_create(&tid[i], NULL, vc(x), NULL);
}
printf("OOOGA BOOGA");
}
printf("OOOGA BOOGA");
for (int i = 0; i < numThreads; i++) {
pthread_join(tid[i], NULL);
printf("Thread %10x joined\n", tid[i]);
fflush(stdout);
}
printf("All Four Threads have exited using join(), exiting program....\n");
fflush(stdout);
exit(EXIT_SUCCESS);
return validateRows(x) + validateCols(x) + validateSubGrids(x); // if all true = valid 9x9, else = not valid 9x9
// return validateSubGrids(x);
}

Pthreads expect a callback function of the form void* func (void*), period. You cannot invent your own function format and expect it to work.
Furthermore the vr(x) etc parameters are function calls - you call the function once then use the result of that to tell pthread_create that it's a pointer to a callback function, which it isn't - it's just nonsense.
Also a function with a return type must always return something.
All of these problems could be avoided early on by configuring the compiler correctly, so that it gives errors upon encountering blatant bugs and invalid C, see What compiler options are recommended for beginners learning C? Correct use of functions is very fundamental stuff and something you need to grasp before moving on to more advanced topics like multi-threading.
Correct use, as was told in the friendly man:
void* vr (void* x) {
validateRows(x);
return NULL;
}
...
pthread_create(&tid[i], NULL, vr, x);

I am not sure if your code compiles but if it does then what will happen is this: When the program runs, then in pthread_create() function, it will call your function vr() and use the return value of vr() as the pointer to the function that should be called when the thread is created.
But vr() does not return any value but it is not of significance here.
The return value of any function is stored somewhere (register, etc.) according to the system. Let's assume that the return value is stored in a register called A. So, vr(x) will be called and then the value in register A will be read and the code will then assume that this value is the pointer to the function that should be called. But A can have any value (because the function vr(x) doesn't return any value and hence it didn't update A) - 0x0, 0x1, 0x75745, etc. And mostly this will be an invalid address (may be it will point to a restricted memory area, or to read only memory, etc.) and so the hardware will raise a memory access violation interrupt/signal which then results in segmentation fault.
Run the following code and you will understand what I am saying.
#include <stdio.h>
#include <pthread.h>
void *f(void *g)
{
printf("Called f().\n");
}
void *x(void *v)
{
printf("Called x().\n");
return (void *)(f);
}
int main(void)
{
pthread_t pt;
pthread_create(&pt, NULL, x((void *)5), NULL);
// join pthread.
pthread_join(pt, NULL);
return 0;
}
Both functions x() and f() will get called when you run the above code.
The output will be:
Called x().
Called f().

Related

A variable in a for loop is changing without being supposed to change in c

Here is the code:
#include <stdio.h> // printf
#include <cs50.h> // get_long
#include <string.h> // strlen
#include <stdlib.h> // stdlib
int credit_test(string input);
int main(void)
{
string userInput;
// Gets user input, and tests if input is valid
bool isInvalid = false;
do
{
userInput = get_string("Number: "); // Prompts user for input
for(int i = 0, evenIndex = strlen(userInput); evenIndex > i; i++)
{
if(userInput[i] - 48 >= 0 && userInput[i] - 48 <= 9 && (strlen(userInput) == 15 || strlen(userInput) == 16)) // Tests if input is valod
{
isInvalid = false;
}
else
{
isInvalid = true;
break;
}
}
}
while(isInvalid);
int keyValidity = credit_test(userInput);
}
int credit_test(string input)
{
int inputLen;
inputLen = strlen(input);
// Even number calculation
int evenArr[16];
int evenSum = 0;
int evenIndex = 0;
printf("Length: %i\n", inputLen);
for(int i = 0; inputLen > i; i++)
{
int n = i * 2;
evenArr[evenIndex] = input[n] * 2;
if(evenArr[evenIndex] > 0)
{
evenArr[evenIndex] -= 96;
}
if(evenArr[evenIndex] > 9) // Code to split doubles
{
int doubleNum = evenArr[evenIndex];
evenArr[evenIndex] = 1;
evenIndex++;
evenArr[evenIndex] = doubleNum % 10;
}
evenIndex++;
evenSum += evenArr[i];
printf("%i\n", evenArr[i]);
printf("Length: %i\n", inputLen);
}
printf("Length: %i\n", inputLen);
printf("Even Sum: %i\n", evenSum);
// Odd number calculation
int oddArr[16];
int oddSum = 0;
int oddIndex = 1;
for(int i = 0; 16 > i; i++)
{
oddArr[i] = input[oddIndex];
if(oddArr[i] > 0)
{
oddArr[i] -= 48;
}
oddSum += oddArr[i];
oddIndex += 2;
printf("%i\n", oddArr[i]);
}
printf("Odd Sum: %i\n", oddSum);
// Validity test
int finalSum = evenSum + oddSum;
int cardType = finalSum % 10;
printf("Final Sum: %i\n", finalSum);
if(cardType == 0 && (input[0] - 48) == 5)
{
printf("MasterCard \n");
}else if (cardType == 0 && (input[0] - 48) == 4)
{
printf("Visa \n");
}else if(cardType == 0 && (input[0] - 48) == 3)
{
printf("Amex \n");
}else
{
printf("Invalid \n");
}
return 0;
}
I just cannot wrap my head around why, but if you run the code, and keep an eye on the "inputLen" variable it stays what it should be, but in the first for loop which gets the even number in the input, the inputLen stays the same, which is correct, but when the loop finishes, for some reason, the variable changes to 0? So would anyone mind to explain as to why its happening? And sorry if the code is all wonky and bad :)
Thanks so much.
This part of the loop
for(int i = 0; inputLen > i; i++)
{
int n = i * 2;
evenArr[evenIndex] = input[n] * 2;
//...
invokes undefined behavior because the expression input[n] can access memory beyond the used array due to using the expression i * 2 as an index. For example then i is equal to inputLen - 1 then n will bi initialized by the expression 2 * ( inputLen - 1 ) and the value of the expression you are using as an index to access elements of the array input but the array does not have so many elements.
Also in this code snippet
if(evenArr[evenIndex] > 9) // Code to split doubles
{
int doubleNum = evenArr[evenIndex];
evenArr[evenIndex] = 1;
evenIndex++;
evenArr[evenIndex] = doubleNum % 10;
}
evenIndex++;
the variable evenIndex can be incremented twice that again can be a reason of undefined behavior when this variable is used as an index to access elements of the array evenArr.

Is there a way to include more than one 'if' conditional for output?

I have this code below (whole code after this section). I am wanting to include more than one casse for this section of the code:
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
casse = 2;
}
if(numberArray[i] == 2)
{
casse = 3;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
casse = 4;
}
}
So far, the above prints '4' when the value '8213' is entered. This is expected since for each round of for loop the 'casse' variable gets updated, by the time it runs the last integer in the array, the value for 'casse' has undergone many replacements and the end result is the last replacement of '4'.
The objective of the code is to determine which cases (casse) have
been met. There can be more than one case (casse) being met, but as it
stands now, it only has room for one case.
#include <stdio.h>
#include <math.h>
int main(void) {
int odo, value, casse;
int i;
printf("please enter a value for the odometer:\n");
scanf("%d", &odo);
value = odo;
casse = 0;
int length = floor(log10(abs(odo))) + 1;
/* count number of digits */
int c = 0; /* digit position */
int n = value;
while (n != 0)
{
n /= 10;
c++;
}
int numberArray[c];
c = 0;
n = value;
/* extract each digit */
while (n != 0)
{
numberArray[c] = n % 10;
n /= 10;
c++;
}
for(i = 0; i < length; i++)
{
printf("%d, ", numberArray[i]);
}
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
casse = 2;
}
if(numberArray[i] == 2)
{
casse = 3;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
casse = 4;
}
}
printf("\n%d\n", casse);
return 0;
}
Output:
please enter a value for the odometer:
8213
3, 1, 2, 8,
4
Expected output:
please enter a value for the odometer:
8213
3, 1, 2, 8,
Not only '4', but also '3', '2'.
Rather than a single variable that keeps track of the last case, you want an array which keeps track of all cases. For a small number of cases, the array can be a fixed size, with the index as case number and the value in the array as the number of times that case was triggered:
int cases[5] = {0};
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
cases[2]++;
}
if(numberArray[i] == 2)
{
cases[3]++;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
cases[4]++;
}
}

C program not running properly on raspberry pi

I'm currently designing a hemming code. This code works perfectly on my computer but when I port it over to my pi, it just does not work properly. I have no idea why and I am pretty new at C and the raspberry pi. Any help would be greatly appreciated.
Below is my full code:
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int main(void){
int bitLen, errorLoc;
printf("\nLength of the data bits: ");
scanf("%d", &bitLen);
char binStr[ bitLen ], binStrErr[ bitLen ];
printf("Data stream without error: ");
scanf("%s", &binStr);
if(strlen(binStr) > bitLen || strlen(binStr) < bitLen)
{
printf("\nLength of data stream given does not match stated input length!");
return 0;
}
printf("Location of data bit that has error: ");
scanf("%d", &errorLoc);
if(errorLoc > bitLen)
{
printf("\nValue given is bigger than the input length!");
return 0;
}
//Number Of Check Bits Needed
int rBit = 1;
while (pow(2, rBit) < (bitLen + rBit + 1))
{
rBit = rBit + 1;
}
int checkBitsArr[rBit];
int checkBitsErrArr[rBit];
//Actual size of array
bitLen = bitLen + rBit;
int binNum[bitLen];
int binNumErr[bitLen];
int size = sizeof(binNum) / sizeof(binNum[0]);
int binNumPos = size;
printf("\nData stream: ");
//Flipping the error bit and storing into another string
printf("\nOriginal data stream: ");
for (int i = 0; i < strlen(binStr); i++){
printf("%c", binStr[i]);
if(i == (strlen(binStr)) - errorLoc){
int temp = ((binStr[i] - '0') == 0) ? 1 : 0;
binStrErr[i] = temp + '0';
}
else{
binStrErr[i] = binStr[i];
}
}
printf("\nData stream with error: ");
for (int i = 0; i < strlen(binStr); i++){
printf("%c", binStrErr[i]);
}
//Filling in the bits into two arrays: One is the correct data stream and one with error
for (int i = strlen(binStr); i >= 0; i--)
{
binNum[binNumPos] = binStr[i] - '0';
binNumErr[binNumPos] = binStrErr[i] - '0';
binNumPos--;
}
printf("\n\n");
//Moving bits to left to make space
int position = 1;
for (int i = size - 1; i >= 0; i--)
{
if ((position & (position - 1)) == 0)
{
for (int c = 0; c <= i; c++)
{
binNum[c - 1] = binNum[c];
binNumErr[c - 1] = binNumErr[c];
}
binNum[i] = 33;
binNumErr[i] = 33;
}
position++;
}
//Settings check bits into place
position = 1;
int checkBitIndex = 0;
for (int i = size - 1; i >= 0; i--)
{
//Get check bit position
if ((position & (position - 1)) == 0)
{
int temp = 0;//number of 1s in relation to the check bit
int tempErr = 0;
int maxNum = (i - position) + 1;
if (maxNum < 0)
maxNum = maxNum + (-1 * maxNum);
//first part of check
while (maxNum < i)
{
if (binNum[maxNum] == 1)
{
temp++;
}
if (binNumErr[maxNum] == 1)
{
tempErr++;
}
maxNum++;
}
int startNum = (i - position) + 1;
//If the start number is less than zero, make it zero
if (startNum < 0)
startNum = startNum + (-1 * startNum);
//Skip check method. Get the next set of check values in relation to the current check bit
for (int x = startNum - (position * 2); x >= 0; x = x - (position * 2))
{
int k = 0;
while (k < position)
{
if (binNum[x + k] == 1)
{
temp++;
}
if (binNumErr[x + k] == 1)
{
tempErr++;
}
k++;
}
}
//Set the value of check bit
binNum[i] = (temp % 2 == 0) ? 0 : 1;
binNumErr[i] = (tempErr % 2 == 0) ? 0 : 1;
//Replace the current value with the correct checkbit
checkBitsArr[checkBitIndex] = binNum[i];
checkBitsErrArr[checkBitIndex] = binNumErr[i];
temp = 0;
tempErr = 0;
checkBitIndex++;
}
position++;
}
printf("\nSEC code: ");
printf("\nOriginal data stream: ");
for (int i = 0; i < size; i++)
{
printf("%d", binNum[i]);
}
printf("\nData stream with error: ");
for (int i = 0; i < size; i++)
{
printf("%d", binNumErr[i]);
}
printf("\n\n");
int checkIndex = (int)pow(2, rBit - 1);
printf("\n\nCheckbits of data bits without error: \n");
for (int i = checkBitIndex - 1; i >= 0; i--)
{
printf("C%d: %d ", checkIndex, checkBitsArr[i]);
checkIndex = checkIndex/2;
}
checkIndex = (int)pow(2, rBit - 1);
printf("\n\nCheckbits of data bits with error: \n");
for (int i = checkBitIndex - 1; i >= 0; i--)
{
printf("C%d: %d ", checkIndex, checkBitsErrArr[i]);
checkIndex = checkIndex/2;
}
checkIndex = (int)pow(2, rBit - 1);
int posError = 0;
printf("\n\nSyndrome code: \n");
for (int i = checkBitIndex - 1; i >= 0; i--)
{
int x = checkBitsErrArr[i] ^ checkBitsArr[i];
if(x == 1){
posError += checkIndex;
}
printf("C%d: %d ", checkIndex, x);
checkIndex = checkIndex/2;
}
printf("\n\n");
printf("\nPosition of error: %d\n\n", posError);
// printf("\n\n");
return 0;
}
These are the inputs for the scanf:
Length of the data bits: 16
Data stream without error: 0011001100110011
Location of data bit that has error: 8
Below are my results on both computer and pi:
Computer result (correct):
Pi result (wrong):
Looks like you have far more than just one problem, but let's just start with the first one:
char binStr[ bitLen ], binStrErr[ bitLen ];
The string you are requesting next contains not just the 16 bytes you get as input, but also an additional sentinel character as the 17th character.
So at this point you already had 2 buffer overflows, which you can already see nicely in the output from the Pi. The same buffer overflow also occurs in the first example, except the memory layout is different enough so that it doesn't yield visible artifacts.
for (int c = 0; c <= i; c++)
{
binNum[c - 1] = binNum[c];
binNumErr[c - 1] = binNumErr[c];
}
Here comes the next buffer overflow, respectively actually an underflow this time. You are writing to binNum[-1] which is a memory location outside of the memory binNum is pointing to.
Anyway, a buffer overflow means the behavior of your program is undefined.
Get used to valgrind or similar tools for checking your code for undefined with regard to such errors.

My program gives the correct output in windows(gcc) but in Linux(gcc) it leads to segmentation fault

This program is to find the epsilon closure of all states of an NFA. I have used the stack to get this done.The program gives the right output when I compiled it using gcc and ran it Windows 10(Command Prompt). But when I compiled with the same compiler and ran it in Linux it results in segmentation fault. I have used any dynamic memory allocation for that matter.
I tried to debug using gdb but not able to find the problem. Detected a segmentation fault after a printf("\n") when displaying the transitions matrix.
It would be very helpful for someone could find the fault. Thanks in advance.
The input is read from a file : nfa.txt.
//states
q0 q1 q2
//input_symbols
0 1
//start_state
q0
//final_state
q2
//transitions of the form : intial_state input final_state
q0 0 q0
q0 e q1
q1 1 q1
q1 e q2
q2 2 q2
The output is as follows:
232 is to represent null transition(Φ) and -1 for ε.
States:
q0
q1
q2
Transitions read
232 0 1 2 -1
0 0 232 232 1
1 232 1 232 2
2 232 232 2 232
e-closure(0) : 0 1 2
e-closure(1) : 1 2
e-closure(2) : 2
Please bear with me because it's a fairly long program.
#include <stdio.h>
#include <string.h> //REMEMBER ME WHILE I'M GONE
#include <errno.h>
#include <stdlib.h>
FILE *file;
int numberOfStates = 0;
int flag = 0;
int states[20];
int j = 0;
int i = 0;
int k = 0;
char a[20];
int transitions[4][5];
int visited[10];
int MAXSIZE = 8;
int stack[8];
int top = -1;
int isempty()
{
if(top == -1)
return 1;
else
return 0;
}
int isfull()
{
if(top == MAXSIZE)
return 1;
else
return 0;
}
int pop()
{
int data;
if(!isempty()) {
data = stack[top];
top = top - 1;
return data;
}
else
printf("Could not retrieve data, Stack is empty.\n");
}
int push(int data) {
if(!isfull()) {
top = top + 1;
stack[top] = data;
}
else
printf("Could not insert data, Stack is full.\n");
}
int IsVisited(int edge)
{
for(int i = 0; i < 10; i++)
if(visited[edge] == 1)
return 1;
return 0;
}
void epsilon_closure(int state)
{
int e_closure[10];
for(int i = 0; i < 10; i++ )
{ e_closure[i] = -1;
visited[i] = 0;
}
push(state);
visited[state] = 1;
while(top != -1)
{
int u = pop();
j = 1;
while(j < 5)
{
//if there is an epsilon transition from the state 'u' to 'v'
if(transitions[j][0] == u && transitions[j][4] != 232) //ASCII of Φ = 232
{
if(! IsVisited(transitions[j][4]))
{
visited[transitions[j][4]] = 1;
push(transitions[j][4]);
}
}
j++;
}
}
j = 0;
for(int edge = 0; edge < 10; edge++)
{
if(visited[edge] == 1)
e_closure[j++] = edge;
}
printf("e-closure(%d) : ",state);
for (i = 0; e_closure[i] != -1; ++i)
printf("%d ", e_closure[i]);
printf("\n");
}
int main()
{
file = fopen("nfa.txt","r");
if (file == NULL) {
perror("fopen");
return -1;
}
//Reading the states
while(!feof(file))
{
fscanf(file,"%s",a);
if(strcmp("//states",a) == 0)
flag = 1;
else if(strcmp("//input_symbols",a) == 0)
break;
if (flag == 1 && a[0] != '/')
{
states[i++] = a[1] - '0';
}
numberOfStates = i;
}
//Display the states of the e-NFA
printf("\nStates : \n");
for(i = 0; i < numberOfStates; i++ )
{
printf("q%d\n",states[i]);
}
i = 1;
flag = 0;
//Reading the transition table
for(int i = 0; i < 4; i++){
for(int j = 0; j < 5; j++)
{
transitions[i][j] = 232;
}
}
while(!feof(file))
{
fgets(a,100,file);
if(a[0] == '/')
{
flag = 1;
}
if(flag == 1 && a[0] != '/')
{
j = 0;
//found a way to store the transition table in a matrix
if(a[3] == 'e')
transitions[(a[1] - '0') + 1][4] = a[6] - '0';
else
transitions[(a[1] - '0') + 1][(a[3] - '0') + 1] = a[6] - '0';
if(a[3] != 'e')
transitions[0][a[3] - '0' + 1] = a[3] - '0'; //input
else
transitions[0][4] = -1; // epsilon input
transitions[(a[1] - '0') + 1][0] = a[1] - '0'; //initial state
}
}
printf("\nTransitions read\n");
for(int i = 0; i < 4; i++){
for(int j = 0; j < 5; j++)
{
printf("%d\t",transitions[i][j]);
}
printf("\n"); //detected segmentation fault here
}
//Calling e-closure for all the states
for(k = 0; k < numberOfStates; k++)
{
epsilon_closure(states[k]);
}
return 0;
}
There is a bug here:
int push(int data) {
if(!isfull()) {
top = top + 1;
stack[top] = data;
}
else
printf("Could not insert data, Stack is full.\n");
}
If top == MAXSIZE-1, isfull() will return false, then you increment top to MAXSIZE and assign stack[MAXSIZE] what is out of bounds and invokes UB. Not having checked the complete source code, I could imagine that incrementing top after assigning would be correct or you have to change isfull() to return true if top >= MAXSIZE-1

Two-Way Insertion Sort not sorting

This is supposed to be a Two-Way insertion sort, but it's not sorting. I'm also supposed to print out the number of assignments for sorting, but right now I just want it to sort.
A separate output array of size 2n+1 is set aside. Initially x[0] is placed into the middle element of the array n.
Continue inserting elements until you need to insert between a pair of elements in the array.
As before you need to make room for the new element by shifting elements. Unlike before,
you can choose to shift all smaller elements one step to the left or all larger elements one step
to the right since there is additional room on both sides of the array. The choice of which
shift to perform depends on which would require shifting the smallest amount of elements.
I can't find much on the internet about this sort except that no one uses it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printArray(int arr[], int len) {
for (int j = 0; j < len; j++)
printf("%d ", arr[j]);
printf("\n");
}
int main() {
FILE *in;
int size_arr = 0;
char ch;
if ((in = fopen("data_a5.txt", "r")) == NULL) {
printf("Error!");
exit(1);
}
do {
ch = fgetc(in);
if (ch == '\n')
size_arr++;
} while (ch != EOF);
rewind(in);
int arr[size_arr];
int sort_arr[2 * size_arr + 1];
int n = 0;
while (!feof(in)) {
fscanf(in, "%d", &arr[n]);
n++;
}
fclose(in);
for (n = 0; n < 2 * size_arr; n++) {
sort_arr[n] = 0;
}
sort_arr[size_arr] = arr[0];
for (n = 1; n < size_arr; n++) {
int index = size_arr;
if (arr[n] <= sort_arr[size_arr]) {
while (!(arr[n] <= sort_arr[index]) && sort_arr[index] != 0 && index >= 0) {
index--;
}
}
if (arr[n] > sort_arr[size_arr]) {
while (!(arr[n] <= sort_arr[index]) && sort_arr[index] != 0 && index < 2 * size_arr) {
index++;
}
}
if (sort_arr[index] == 0) {
sort_arr[index] = arr[n];
} else {
int next_R, next_L = index;
while (sort_arr[next_R] != 0 && next_R <= 2 * size_arr) {
next_R++;
}
while (sort_arr[next_L] != 0 && next_L >= 0) {
next_L--;
}
int R_move = next_R - index;
int L_move = index - next_L;
if (R_move > L_move) {
while (L_move <= index) {
sort_arr[L_move] = sort_arr[L_move + 1];
L_move++;
}
sort_arr[index] = arr[n];
} else {
while (R_move >= index) {
sort_arr[R_move] = sort_arr[R_move - 1];
R_move--;
}
sort_arr[index] = arr[n];
}
}
}
printArray(arr, size_arr);
return 0;
}
I'm not sure this solves all problems but it is a problem you must fix.
This code
int next_R, next_L = index;
while(sort_arr[next_R] != 0 && next_R <= 2*size_arr)
has undefined behavior as next_R is uninitialized.
Maybe you want:
int next_R = index, next_L = index;
^^^^^
while(sort_arr[next_R] != 0 && next_R <= 2*size_arr)
In any case you have to initialize next_R before using it.
I also find this line strange:
printArray(arr, size_arr);
^^^
Seems you are printing the original array instead of the sorted array.
May be you want:
printArray(sort_arr, size_arr);
^^^^^
There are some problems in your code:
when you scan the file in the first pass, you should count the number of integers instead of the number of characters.
when inserting, your loops are off by one: the tests should read while (L_move < index) and while (R_move >= index)
while (!feof(in)) is always wrong, you should instead write while (fscanf(in, "%d", &arr[n]) == 1) {...
you should probably allocate the arrays arr and sort_arr instead of defining them as VLAs with automatic storage to prevent undefined behavior on large input files.
you should use binary search into the sorted portion, otherwise your algorithm has a basic complexity of O(N2) that dwarfs the small gain obtained from the minimisation of the insertion phase.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
void print_array(const int arr[], int len) {
for (int j = 0; j < len; j++)
printf("%d%c", arr[j], " \n"[j == len - 1]);
}
int main(void) {
FILE *in;
int size_arr, n, start;
int value;
if ((in = fopen("data_a5.txt", "r")) == NULL) {
printf("Cannot open input file %s\n", "data_a5.txt");
exit(1);
}
for (size_arr = 0; fscanf(in, "%d", &value) == 1; size_arr++)
continue;
rewind(in);
int *arr = calloc(2 * size_arr + 1, sizeof(*arr));
if (arr == NULL) {
printf("Cannot allocate memory for %d entries\n", size_arr);
exit(1);
}
start = size_arr;
for (n = 0; n < size_arr && fscanf(in, "%d", &value) == 1; n++) {
/* insert value into the sorted array */
int a, b;
for (a = start, b = start + n; a < b;) {
int mid = a + (b - a) / 2;
if (arr[mid] < value) {
a = mid + 1;
} else {
b = mid;
}
}
/* insert value at offset b */
if (b - start < start + n - b) {
/* shift left portion to the left */
for (int i = start--; i < b; i++) {
arr[i - 1] = arr[i];
}
b--;
} else {
/* shift right portion to the right */
for (int i = start + n + 1; --i > b;) {
arr[i] = arr[i - 1];
}
}
arr[b] = value;
}
fclose(in);
print_array(arr + start, n);
free(arr);
return 0;
}
like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printArray(int arr[], int len){
while(len--)
printf("%d ", *arr++);
printf("\n");
}
int main(void){
int size_arr = 10;
int arr[size_arr];
int sort_arr[2 * size_arr + 1];
for(int i = 0; i < size_arr; ++i)
arr[i] = -50 + rand() % (100 + 1);
puts("before:");
printArray(arr, size_arr);
int left, right;
sort_arr[left = right = size_arr] = arr[0];
for (int n = 1; n < size_arr; ++n){
int v = arr[n];
if(v <= sort_arr[left]){
sort_arr[--left] = v;
} else if(v >= sort_arr[right]){
sort_arr[++right] = v;
} else {
int L = left, R = right, M, MV;
while(L <= R){
M = L + (R-L)/2;
MV = sort_arr[M];
if(MV < v)
L = M + 1;
else if(v < MV)
R = M - 1;
else
break;
}
//M: insert position
enum { LEFT, RIGHT } CHOICE;
if(v == MV){
int ML = M, MR = M;
while(sort_arr[ML-1] == sort_arr[ML])
--ML;
while(sort_arr[MR] == sort_arr[MR+1])
++MR;
if( ML-left >= right-MR){
M = MR+1;
CHOICE = RIGHT;
} else {
M = ML;
CHOICE = LEFT;
}
} else if(v > MV){
++M;
CHOICE = M-left+1 > right-M;// ? RIGHT : LEFT;
} else {
CHOICE = M-left-1 > right-M;// ? RIGHT : LEFT;
}
if(CHOICE == RIGHT){
memmove(sort_arr + M+1, sort_arr + M, (right-M+1)*sizeof(v));
sort_arr[M] = v;
++right;
} else {
memmove(sort_arr + left-1, sort_arr + left, (M-left)*sizeof(v));
sort_arr[M-1] = v;
--left;
}
}
}
puts("after:");
printArray(sort_arr + left, size_arr);
return 0;
}

Resources