Segmentation Fault with Merge Sort - c

I've recently begun brushing up on my C again after having not touched it for some time. So, I started by trying to implement merge sort but after looking at these lines for about an hour, I've failed to determine what is wrong.
int main(int argc,char** argv){
printf("test\n");
int x;
int input[] = {1,2,3};
int start=0;
int end=2;
for (x=0;x<5;x++){
//printf("%i\n",x);
}
printf("Run mergeSort in main \n");
mergeSort(input,start,end);
}
void mergeSort(int input[], int start, int end){
printf("Running merge %i %i",start,end);
int middle = (start + end)/2;
if (start < end){
mergeSort(input,start,middle);
mergeSort(input,middle+1,end);
merge(input,start,middle,end);
}
}
When I run this program, the first line "test" will print then "Run merge sort in main" but
printf("Running merge %i %i",start,end);
does not get executed which leaves me confused. I can't find any memory allocation issues or maybe I'm missing something very obvious.
Note that the merge function has been implemented on the side, but that portion of the code was not relevant to this problem directly so I did not include it.
EDIT Remaining Code:
void merge(int input[],int start, int middle, int end){
int save_start = start;
int temp[end-start+1];
int index = 0;
printf("Start merge");
while (start<=middle || middle+1<=end){
if (input[start]<input[middle]){
temp[index] = input[start];
start++;
} else {
temp[index] = input[middle];
middle++;
}
index++;
}
while (start<=middle){
temp[index] = input[start];
start++;
}
while (middle+1<=end){
temp[index] = input[middle];
middle++;
}
int i=0;
int a;
for (a=save_start;i<index;a++,i++){
input[a]=temp[i];
}
}

Most likely your output is buffered and is just waiting around to get printed. Add a \n to that string or call fflush(stdout).
As far as your segmentation fault is concerned, you haven't shown us enough code. Use a debugger to get a backtrace and you may find out some more information.
Edit: You have some array index bugs in your merge function. Notice that you're moving middle during the first loop there - what does that do to the loop condition? Hint: you need to stop at the actual middle position, not keep going once start gets past that point.
Edit 2: You have some off-by-one errors in there too.
Edit 3: Your || should be &&.

I believe your mistake is here: while (start<=middle || middle+1<=end).
start<=middle || middle+1<=end is true when one or more of these is true: start<=middle or middle+1<=end, causing your code to read and write out of bounds of your arrays in that loop.
start<=middle && middle+1<=end is true when all of these are true: start<=middle and middle+1<=end, causing your loop to break when it might otherwise read and write out of bounds of your array.
You probably mean while (start<=middle && middle+1<=end).

Related

C: Function not behaving as intended when called by "if" statement

I'm a C beginner and am working on a program that registers flights using structs. Each flight has a code that must follow a certain structure: FLI-XXXX, X being integers. I'd like to use the integers part of the code later on, so I thought the best way to scan for it was using both fgets and scanf. After validating the code using auxiliary variables, I would later write it to the flights struct. However, I'm stuck at the validating part.
The problem is, whenever I call the function that validates a code (opt1) inside an if statement, it runs twice and only works as intended the second time around. Here's my code:
#include <stdio.h>
#include <string.h>
typedef struct
{
int num;
char code[5];
}fl;
fl flight[9999];
int Valid(char a[], int b)
{
if((strlen(a) != 4) || (b<0 || b>9999)){
return 0;
}
else if(a[0] !='F' || a[1] !='L' || a[2] !='I' || a[3] != '-'){
return 0;
}
return 1;
}
void opt1(fl a[]){
char tempCode[5];
int tempNum;
do
{
puts("Insert code:");
fgets(tempCode, 5, stdin);
scanf("%d", &tempNum);
puts("");
if (Valid(tempCode, tempNum))
{
printf("Flight %s%d registered. \n", tempCode, tempNum);
}
else
{
puts("Flight # invalid.");
}
} while (Valid(tempCode, tempNum)==0);
}
int main() {
int opt;
//calling opt1 works as intended
opt1(flight);
//calling inside if statement runs opt1() twice, only the second time as intended
scanf("%d", &opt);
if(opt==1){
opt1(flight);
}
return 0;
}
And here's an input:
FLI-1234
1
FLI-1234
That returns:
Flight FLI-1234 registered.
Insert code:
Flight # invalid.
Insert code:
Flight FLI-1234 registered.
I'm not sure why this is happening. Can anyone guide me in the right direction, please? Thank you.

How to use recursion in quicksort algorithm in c?

This is my first time posting so bear with me! I have to make a quicksort algorithm as an assignment for university, using c. However, when I try running the program a pop-up window opens up and informs me that the exe has stopped working. So then I started debugging and I found that the problem appears when the program enters the recursion process, as I receive around those lines a SIGSEGV type error. Unfortunately I cant find the problem so that's why I'm posting here my code, hoping that you can help me. Any further advice about my code in general will be appreciated. Thanks!
#include <stdio.h>
#include <string.h>
#define SIZE 20
void quicksort(int *first, int *last);
main()
{
FILE *fp;
int *ptr, arr[SIZE], k;
ptr=arr;
fp=fopen("numbers.txt", "r");
printf("Initial array before sorting:\n");
for (k=0; k<SIZE; k++)
{
fscanf(fp, "%d", ptr);
printf("Element[%d]:\t%d\n", k+1, *ptr);
ptr++;
}
fclose(fp);
printf("Final array after sorting:\n");
quicksort(arr, arr+SIZE-1);
for (k=0; k<SIZE; k++)
{
printf("Element[%d]:\t%d\n", k+1, *(arr+k));
}
}
void quicksort(int *first, int *last)
{
int *item_left, *item_right, *i, *j, *pivot, temp, check_left=0, check_right=0, limiter=0;
pivot=last;
while (!check_left && !check_right && limiter<10)
{
for (i=first; i<last; i++)
{
if (*i>*pivot)
{
item_left=i;
check_left=1;
break;
}
}
for (j=last; j>first; j--)
{
if (*j<*pivot)
{
item_right=j;
check_right=1;
break;
}
}
if (check_left==1 && check_right==1)
{
temp=*item_left;
*item_left=*item_right;
*item_right=temp;
check_left=0;
check_right=0;
}
limiter++;
}
temp=*item_right;
*item_right=*pivot;
*pivot=temp;
if (last-first>1)//-------problem
{
quicksort(first, item_left-1);
quicksort(item_left, last);
}//----------problem
}
So I checked the code again and I found the problem. You see, I declared some local variables in the function I was calling. This was causing trouble in the computer's memory, as every time the function was called again, it was told to create the same variables which were already created and stored in the memory. So what I did is to make all those variables needed global. This way they are created only one time.

CUDA code not processing if block properly

Stuck at if block right below //step 5, the issue is that the code will not progress into or after the given if block. I need to figure out how to get this particular issue settled before starting the task of generating parallel code. If you run the code you will see one print statement that indicates the value of "one" and another two for "i" and "j". After the if block begins, none of the other print statements are hit. As a result I am quite stuck, I am aware that this is a specific issue, however, I cannot seem to determine it's cause.
Any help is appreciated!
Thanks in advance!
Input file sample.
>386.fasta.screen.Contig1
GAGTTTGATCCTGGCTCAGAATCAACGCTGGCGGCGCGCTTAACACATGC
AAGTCGAACGAGAAAGTGGAGCAATCCATGAGTACAGTGGCGTACGGGTG
AGTAACACGTGGGTAATCTACCTCTTAGTGGGGAATAACTTTGGGAAACC
GAAGCTAATACCGCATAAGCTCGAGAGAGGAAAGCAGCAATGCGCTGAGA
GAGGAGCCCGCGGCCGATTAGCTAGTTGGCAGGGTAAAAGCCTACCAAGG
CAGAGATCGGTAGCCGGCCTGAGAGGGCACACGGCCACACTGGCACTGAA
ACACGGGCCAGACTCCTACGGGAGGCAGCAGTGGGGAATCTTGCACAATG
GGGGCAACCCTGATGCAGCGACGCCGCGTGAGCGATGAAGCCCTTCGGGG
TGTAAAGCTCTTTCGTCAGGGAAGATAGTGACGGTACCTGGAGAAGCAGC
TGCGGCTAACTACGTGCCAGCAGCCGCGGTAATACGTAGGCAGCGAGCGT
TGTTCGGAGTTACTGGGCGTAAAGGGTGTGTAGGCGGTTGTTTAAGTTTG
GTGTGAAATCTCCCGGCTCAACTGGGAGGGTGCGCCGAATACTGAGCGAC
TAGAGTGCGGGAGAGGAAAGTGGAATTCCTGGTGTAGCGGTGAAATGCGT
AGATATCAGGAGGAACACCGGTGGTGTAGACGGCTTTCTGGACCGTAACT
GACGCTGAGACACGAAAGCGTGGGTAGCAAACAGGATTAGATACCCTGGT
AGTCCACGCCCTAAACGATGCATATTTGGTGTGGGCAGTTCATTCTGTCC
GTGCCGGAGCTAACGCGTTAAATATGCCGCCTGGGGAGTACAGTCGCAAG
GCTGAAACTCAAAGGAATTGACGGGGGCCCGCACAAGCGGTGGAGCATGT
GGTTTAATTCGACGCAACGCGAAGAACCTTACCTGGGCTCGAACGGCTTC
CCAACGCCGGTAGAAATATCGGTACCCCGCAAGGGGGTGGAATCGAGGTG
CTGCATGGCTGTCGTCAGCTCGTGTCGTGAGATGTTGGGTTAAGTCCCGC
AACGAGCGCAACCCTTGTCCTGTGTTGCCATGCCGCAAGGCGGCACTCGC
AGGAGACCGCCAGCGATAAGCTGGAGGAAGGTGGGGATGACGTCAAGTCC
TCATGGCCTTTATGTCCAGGGCTACACACGTGCTACAATGGCCGGTACAA
AGCGTCGCTAACCTGCGAAGGGGAGCCAATCGCAAAAAACCGGTCTCAGT
TCGGATTGCAGGCTGCAACCCGCCTGCATGAAGCTGGAATCGCTAGTAAT
GGCAGATCAGCACGCTGCCGTGAATACGTTCCCGGGCCTTGTACACACAT
/********************************
Based on code by:
Lorenzo Seidenari (sixmoney#virgilio.it)
*********************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#define MAX_SEQUENCE_LENGTH 100000
int n;
int m;
int levenshtein_distance(char *s,char*t);
int minimum(int a,int b,int c);
//-----------------------------------------------------------------------------
void cleanString(char string[]) {
//Removes all spaces from string pointed to by "string", converts characters
//to uppercase, and deletes a terminating newline character.
int i, current;
int length = strlen(string);
current = 0;
for(i=0;i<length;i++) {
if(string[i]=='\n') {
string[current++] = '\0';
break;
}
else if(string[i]!=' ') {
string[current++] = toupper(string[i]);
}
}
}
//-----------------------------------------------------------------------------
int importFASTA(char *filename, char *sequence) {
//Reads a file, located at path specified by "filename", containing a FASTA
//sequence. It finds the first full, complete sequence in the file, stores
//it in "sequence", and returns the length of the sequence, or -1 on failure.
FILE *fastaFile;
char input[256];
int readFlag; //set to 1 once a sequence has been read in
int length;
//open the file
if((fastaFile = fopen(filename, "r")) == NULL) {
return -1;
}
sequence[0] = '\0';
//read the full first sequence, discarding unnecessary headers
readFlag=0;
length = 0;
while(fgets(input,256,fastaFile)!=NULL) {
//is it a header or a comment?
if(input[0]=='>' || input[0]==';') {
if(readFlag) break;
else continue;
}
else readFlag = 1;
cleanString(input);
length += strlen(input);
strncat(sequence,input,MAX_SEQUENCE_LENGTH-length - 1);
}
//Add a terminatng null character, just in case
sequence[length] = '\0';
fclose(fastaFile);
return length;
}
/****************************************/
/*Implementation of Levenshtein distance*/
/****************************************/
__global__ void levenshtein_distance(char *s,char*t, int one, int two)
/*Compute levenshtein distance between s and t*/
{
//Step 1
int k,i,j,cost,*d;
int distance = 0;
if(one!=0&&two!=0)
{
d=(int *)malloc((sizeof(int))*(two+1)*(one+1));
two++;
one++;
//Step 2
for(k=0;k<one;k++){
d[k]=k;
}
for(k=0;k<two;k++){
d[k*one]=k;
}
//Step 3 and 4
for(i=1;i<one;i++){
for(j=1;j<two;j++)
{
//Step 5
printf("%d %d %d\n", one, i, j);
if(s[i-1]==t[j-1]){
cost=0;
printf("%d %d %d\n", one, i, j);
}
else{
cost=1;
printf("%d %d %d\n", one, i, j);
}
printf("%d %d %d\n", one, i, j);
//Step 6
int min = d[(j-1)*one+i]+1;
if (d[j*one+i-1]+1 < min)
min = d[j*one+i-1]+1;
if (d[(j-1)*one+i-1]+cost < min)
min = d[(j-1)*one+i-1]+cost;
d[j*one+i] = min;
}
distance=d[one*two-1];
free(d);
printf("%d\n", distance);
}
}
else
printf ("-1");
}
int main(int argc, char *argv[]) {
char A[MAX_SEQUENCE_LENGTH+1];
char B[MAX_SEQUENCE_LENGTH+1];
if(argc < 3) {
printf("Usage: new_edit_distance <sequence1> <sequence2>\n");
printf("<sequence1>: file containing the first sequence, FASTA format\n");
printf("<sequence2>: file containing the second sequence, FASTA format\n");
return EXIT_FAILURE;
}
n = importFASTA(argv[1],A);
m = importFASTA(argv[2],B);
levenshtein_distance<<<1, 1>>>(A,B, n, m);
cudaDeviceSynchronize();
printf ("%s\n", cudaGetErrorString(cudaGetLastError()));
return EXIT_SUCCESS;
}
I get it now. You took straight serial C/C++ code, dropped it into a kernel, intended to run that kernel as a single thread, and then want to proceed from there.
The idea is plausible, but you're missing a key fact about CUDA and GPUs: they can't directly access host memory.
So when you set up A and B like this:
char A[MAX_SEQUENCE_LENGTH+1];
char B[MAX_SEQUENCE_LENGTH+1];
....
n = importFASTA(argv[1],A);
m = importFASTA(argv[2],B);
those are ordinary variables that live in host memory. GPU (ordinary CUDA) code can't directly access host memory. So when you pass those pointers to a kernel like this:
levenshtein_distance<<<1, 1>>>(A,B, n, m);
the GPU code will try and dereference those A and B pointers and will fault (unspecified launch failure).
Every CUDA program has the following basic sequence:
copy data to the GPU
perform computations on the GPU
copy results back
You've tried to do step 2 without step 1. It won't work.
Since I'm not able to run your program since I don't have valid input files, I'll make the following suggestion. I assume you know little or nothing about CUDA. Try adding lines like this:
n = importFASTA(argv[1],A); // no change
m = importFASTA(argv[2],B); // no change
char *d_A, *d_B; // add this line
cudaMalloc(&d_A, MAX_SEQUENCE_LENGTH+1); // add this line
cudaMalloc(&d_B, MAX_SEQUENCE_LENGTH+1); // add this line
cudaMemcpy(d_A, A, MAX_SEQUENCE_LENGTH+1, cudaMemcpyHostToDevice); // add
cudaMemcpy(d_B, B, MAX_SEQUENCE_LENGTH+1, cudaMemcpyHostToDevice); // add
levenshtein_distance<<<1, 1>>>(d_A,d_B, n, m); //modify parameters
n and m don't need to be handled any differently since you are passing those by value.
And add proper cuda error checking to your code.
EDIT: after some further analysis, it's clear that this sequence is not correct:
distance=d[one*two-1];
free(d);
printf("%d\n", distance);
}
}
You are freeing d on every iteration of the i loop. That cannot possibly be correct. I suggest you go back to square one and get your serial code working first, in ordinary serial C code, before dropping it into a cuda kernel this way. If you move that free statement outside the i loop, then your kernel runs for a very very long time. Be advised that in-kernel printf is limited in the amount of output that can be easily generated.
I'm not going to debug your code any further for you. Get your serial code working first, then figure out a way to create a kernel without massive quantities of printout.
A final comment: I said above your approach is "plausible". That it means it could be made to work, i.e produce the same behavior as the same code executing on the host. It does not mean it will run fast. This is not how you get acceleration out of a GPU (running a single block of a single thread). I assume you already know this based on your comment "how to get this particular issue settled before starting the task of generating parallel code." But I think the disclaimer is appropriate anyway.

Why isn't my write method initialised?

I have been trying to write words that are given by the user in the command shell,but for some reason my program instantly quits after the read() function,so the text in main() :"in main2\n" is never even written. I have been trying to locate my problem for about an hour now and can't seem to find it.
# include <stdio.h>
void write_zin(const char* zin,int length_zin){
const char * runner =zin;
printf("out of loop\n");
while(runner!=(runner+length_zin)){
printf("%c",*runner);
runner++;
}
}
void read(char* zin,int NUMBER_LETTERS,int NUMBER_WORDS){
int i ;
char woord[NUMBER_LETTERS+1];
zin[0]='\0';
for(i =0;i<NUMBER_WORDS;i++){
printf("Give a word with %i letters\n",NUMBER_LETTERS);
scanf("%s",woord);
strcat(zin,woord);
strcat(zin,'\0');
}
strcat(zin,'\0');
}
int main(){
const int NUMBER_LETTERS = 5;
const int NUMBER_WORDS = 2;
char zin[(NUMBER_LETTERS+1)*NUMBER_WORDS];
printf("in main 1\n");
read(zin,NUMBER_LETTERS,NUMBER_WORDS);
printf("in main 2\n");
write_zin(zin,(NUMBER_LETTERS+1)*NUMBER_WORDS);
printf("in main3\n");
return 0;
}
There are a couple errors in your code:
Function void read(char* zin,int NUMBER_LETTERS,int NUMBER_WORDS)
If you concatenate words separated by '\0' you will end having just one string, because every string function will stop at the first '\0' and will not process further characters. So you cannot use strcat(zin,'\0');
If you want to mark the separation between strings use another special character as '\n' The final function will be:
void read(char* zin,int NUMBER_LETTERS,int NUMBER_WORDS){
int i ;
char woord[NUMBER_LETTERS+1];
for(i =0;i<NUMBER_WORDS;i++){
printf("Give a word with %i letters\n",NUMBER_LETTERS);
scanf("%s",woord);
strcat(zin,woord);
}
}
2. Function void write_zin(const char* zin,int length_zin)
You cannot ever change the condition of a loop inside a loop. That is what you are doing, because runner is always changing inside the loop, and in addition it is part of your condition.
while(runner!=(runner+length_zin)){
printf("%c",*runner);
runner++;
}
The final function is:
void write_zin(const char* zin,int length_zin){
const char * runner =zin;
printf("out of loop");
while(*runner){
printf("'%c'",*runner);
runner++;
}
}

what's the meaning of the circle node in pdgs which is generated by frama-c

I use frama-c tool to analyse the code below.
int main (int argc, char *argv[])
{
int i,a;
for (i = 0; i < 100; i += 1)
{
a=0;
if (a==0)
{
continue;
}
else
{
break;
}
}
return 0;
}
the cmd is
frama-c -pdg -dot-pdg graph main.c
My question is about the control dependence. what's the circle node means? I try to explain the "while" node, maybe it stand for one time loop , because a loop start from "i<100",so there a control dependence ("i<100" ------o "while" ). Is what I guess right ? but what is the "break" node mean? I guess that node "goto __Cont;" is related to the "break;" statement in the "else" block.
I think I have no clear abstract model in my head for understanding the control dependence completely and accurately . Would you help me or give me any suggestion ?. Many Thanks in Advance Tao.
Use the command frama-c -print main.c to see how the program was translated (I include the translated version below).
The statement goto __Cont; in the normalized version is the translation of continue; in the original.
And, as Binyamin said, the for loop was normalized into a while loop.
int main(int argc, char **argv)
{
int __retres;
int i;
int a;
i = 0;
while (i < 100) {
a = 0;
if (a == 0) { goto __Cont; }
else { break; }
__Cont: /* internal */ i ++;
}
__retres = 0;
return (__retres);
}
Most of it is self explanatory:
circle - flow control (branching)
rhombus - condition (a == 0 etc.)
square - assignment
Your for loop was translated to a while loop

Resources