Why does my recursive function cause a segmentation fault? - c

In the following code I am trying to solve the towers of Hanoi problem. Why am I getting a segmentation fault (core dump)?
Segmentation fault should occur when I try to access unreachable memory but in this program I am not trying to access any unreachable memory.
#include <stdio.h>
#include <stdlib.h>
void steps(int n, int t, int p)
{
int i, k = 6 - (p + t);
if (n == 1) {
printf("%d-->%d\n", n, t);
}
for (i = 0; i < 2; ++i) {
if (i == 0) {
steps(n - 1, k, p);
printf("%d-->%d\n", n, t);
} else {
steps(n - 1, t, k);
}
}
}
int main()
{
int n;
printf("Enter the value of n: ");
scanf("%d", &n);
steps(n, 3, 1);
return 0;
}

You are accessing memory you can't access. It just isn't obvious in the code (like a dangling pointer). Recursion is tricky; you can easily overflow the stack. The stack stores information when you enter a function (registers or addresses of parameters, saved values of registers used in the calling function and the called function, and a return pointer (where to jump to when you finish the function) basically.
The stack has a certain size. It might be quite large, but it is finite. In recursion, you keep calling the same function from within itself. If this happens too many times, you will "overflow the stack" -- that is, try to "push" more info onto the stack when it is already full, which means at an address past the end of the stack -- memory you may not have access to. (If you do have access to it, you maybe overwriting one of your variables or some such.)
When you have recursed far enough, you must return from your function without calling it again. Probably in your n==1 "if".

In the base case of your recursion, you do not have any return statement so your code goes on for infinite time(time limit exceeded), you should try like this:
if(n==1)
{
printf("%d-->%d\n", n, t);
return ;
}

Related

Why does c print a different array the second time it's printed?

My cousin has a school project and we can't figure out why is the array different the second time it's printed when there is no values changing in between?
Basically you enter a number which states how many rows/columns will the matrix have, and during first loop he assigns a number to every position and prints out the random number. However, the second time we go through the matrix the numbers are different and it seems that they are copied through the matrix from bottom left corner to top right corner for some reason. It seems strange to us because we never assign a different value to a position in the array after defining it for the first time.
int i,j,n,matrica[i][j],suma=0;
srand(time(NULL));
printf("\nunesi prirodan broj N[3,20] = \n");
scanf("%d",&n);
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
matrica[i][j]=rand()%100;
printf("%d, %d = %4d ",i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
printf("\n");
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
printf("%d, %d = %4d ", i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
And here is the result of this (the code I pasted here has 2 prints, and in the image there is 3 but every time you go through the matrix after the first time it's going to be the same):
We need to use malloc to allocate the dynamic amount of memory.
After
scanf("%d",&n) // PS You should check the return value - read the manual page
Put
matrica = malloc(sizeof(int) * n * n);
And declare it as
int *matrica;
Then replace
matrica[i][j]
with
matrica[i * n + j]
And after you have finished with matrica - use free i.e.
free(matrica);
int i,j,n,matrica[i][j]
At this point I must ask, what value do you think i and j will have? Right there you're invoking undefined behaviour by referring to variables declared with automatic storage duration which you've not initialised. Anything after this point is... undefined behaviour.
Having said that, I noticed a few other parts that look strange. Which book are you reading? The reason I ask is that the people I know to be reading reputable textbooks don't have these problems, thus your textbook (or resource, whatever) mustn't be working for you...
I can't read the commentary inside of the string literals, which is a shame, since that's usually quite valuable contextual information to have in a question. Nonetheless, moving on, if this were me, I'd probably declare a pointer to an array n of int, after asking for n, like so:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t n;
printf("Enter n, please: ");
fflush(stdout);
if (scanf("%zu", &n) != 1 || n == 0 || SIZE_MAX / n < n) {
puts("Invalid input or arithmetic overflow...");
return -1;
}
int (*array)[n] = malloc(n * sizeof *array);
if (!array) {
puts("Allocation error...");
return -1;
}
/* now you can use array[0..(n-1)][0..(n-1)] as you might expect */
free(array);
}
This should work for quite high numbers, much higher than int array[n][n]; would in its place... and it gives you that option to tell the user it was an "Allocation error...", rather than just SIGSEGV, SIGILL, SIGBUS or something...
... but nothing would be more optimal than just saving the seed you use to generate the random numbers, and the user input; that's only two integers, no need for dynamic allocation. There's no point storing what rand generates, amd you realise this, right? rand can generate that output purely using register storage, the fastest memory commonly available in our processors. You won't beat it with arrays, not meaningfully, and not... just not.

mpz_add() causes segmentation Fault at large program

My problem is the following. I have to write a program which calculates a really large element of the Fibonacci numbers (lowest it has to calculate is the pow(2,10)th member, largest is pow(2,20)th member). For this I'm using GMP's mpz_t and it's functions for calculations.
I use a tail recursive algorithm for this (later on I have to make it run parallel). The issue is that it runs for a while, then suddenly: Segmentation fault (core dumped).
I show you my code, explain it, so you don't have to waste your time figuring it out and tell you what I got to know.
int main(int argc, char** argv){
char result[1000000]; char *r; r = result;
long int n;
mpz_t num;
mpz_init(num);
double start_t, end_t, total_t;
start_t = omp_get_wtime();
for(int i = 0; i < 11; i++){
n = pow(2,i+10);
fibo(num,n);
char *d = mpz_get_str(NULL,10,num);
strcpy(r,d);
printf("The %ld. element of Fibonacci is: %s\n",n,result);
fflush(stdout);
memset(result, 0, sizeof result);
}
end_t = omp_get_wtime();
total_t = end_t - start_t;
printf("Time of running: %.6f\n",total_t);
return 0;
}
The main() function basically creates (and initializes) the variables, sets up the time measurement and in a for loop calls the fibo() function, getting the result and printing it. When everything is done, the program writes out the time of running and quits.
void fibo(mpz_t res, long int n){
if(n == 0){
mpz_set_str(res,"0",10);
return;
}else{
mpz_t temp1;
mpz_t temp2;
mpz_init_set_si(temp1,0);
mpz_init_set_si(temp2,1);
fiboTail(res,n,1,temp1,temp2);
mpz_clear(temp1);
mpz_clear(temp2);
}
}
fibo() gets 2 arguments, first one is mpz_t (for the ones who don't know, this is a pointer and it's going to belong to the one that got created in the main() so the final value is going to land back there for further usage) and the second one is the number of the element we need to calculate. If the element number is 0, we simply give back "0", otherwise we make two mpz_t variables, set one two "0", the other to "1" and hand them to the fiboTail() along with some other arguments.
void fiboTail(mpz_t res, long int n, long int m, mpz_t fibPrev, mpz_t fibCurrent){
if(n == m){
mpz_set(res,fibCurrent);
}else{
mpz_add(fibPrev,fibPrev,fibCurrent);
fiboTail(res,n, m + 1, fibCurrent, fibPrev);
}
}
So this one basically is the core. m counts how many additions we have done, on which element we are at, n is the number of element we need, fibCurrent and fibPrev is the current and previous Fibonacci number respectively.
Sorry for the dumb explanation, I figure most of you knew this without me trying to explain.
So, this program is really fast. The problem (Segmentation fault) happens when it's counting the 131072th element (sometimes on a smaller one, its...random(?)). Then the program stops about the same number of addition/m value (not always on the same one, but close to there) and the previously mentioned error message appears. I use gcc to compile (actually using Makefiles), so I added the -g switch and used gdb to get more info. Here is what I found:
I ran the program in gdb and used backtrace which produce this.
Here is the detailed stack info using info frame on frame #0-5. The error occurs at the mpz_add call, but I don't know why.
If you need any more information, I can give them, but for now I don't know what else would be useful.
Sorry for the long post, thanks for the answers in advance!
Edit:
As it seems that mpz_add dies at a point, I got out the info of the call, you can see it: i.imgur.com/XOpTve1.png (Sorry, can't post more than 2 links :/ )
Not sure if this will help, but here is the Lucas sequence method for finding fibonacci(n), which is fast and could be used to confirm your results (such as size of the result which may be too big). It's similar to implementing fibnoacci(n) in matrix form and using repeated squaring to raise the matrix to the nth power where fib(n) = M^n x fib(0), where M is a 2 by 2 matrix, and fib() is a 2 element vector. The Lucas sequence function takes 1 + log2(n) loops to run, so for n=2^20, it would take 21 loops.
uint64_t fibl(uint64_t n) {
uint64_t a, b, p, q, qq, aq;
a = q = 1;
b = p = 0;
while(1) {
if(n & 1) {
aq = a*q;
a = b*q + aq + a*p;
b = b*p + aq;
}
n >>= 1;
if(n == 0)
break;
qq = q*q;
q = 2*p*q + qq;
p = p*p + qq;
}
return b;
}
Try this: instead of repeatedly making tail calls which might not be optimized, iteratively calculate the values or use memoization. The program is probably running out of memory somewhere.
What you got is just the plain old stack overflow due to the recursive nature of your fiboTail function.
First, note that you don't need a debbuger to check for this, just place some printfs around fiboTail and you'll see that mpz_add executes fine and the fault happens just at the fiboTail call, before the entry to the next fiboTail with (n,m) values like (131072,115265), (131072,115224), and (131072,115218).
You can get rid of recursion rewritting fiboTail as
void fiboTail(mpz_t res, long int n, long int m, mpz_t fibPrev, mpz_t fibCurrent) {
mpz_t tmp;
mpz_init(tmp);
for (long int i = m; i < n; i++) {
mpz_add(fibPrev, fibPrev, fibCurrent);
mpz_set(tmp, fibPrev);
mpz_set(fibPrev, fibCurrent);
mpz_set(fibCurrent, tmp);
}
mpz_set(res, fibCurrent);
}
Of course, you can simplify the call by removing some parameters, or just place its code inside fibo.
In my (very old) PC, Core I5 2th gen 4Gb RAM, I get (replaced omp_get_wtime with clock from time.h, though):
Time of running: 11.068110
and it seems all elements check, up to the 1048576th which has 219140 chars, and first digits check with the answers from WolframAlpha.
If recursion is so important (note that you don't necessarily need it for parallel programming), you can either increase stack size (at compile or runtime), or you can check your compiler setting to reuse the fiboTail stack frame, since you are using tail recursion.

Reverse by Recursion

My code for finding reverse by recursion says Segmentation Fault
Why?And how to find reverse by recursion?
What is wrong with my code?
#include<stdio.h>
int rev(int);
main()
{
int a,b;
scanf("%d",&a);
b=rev(a);
printf("%d",b);
}
int rev(int x)
{
int q,r;
static int p=0;
p=p*10+(x%10);
r=x/10;
q=rev(r);
return(p);
}
You are using q=rev(r); without any conditions, i.e. you jump deeper and deeper into the recursive calls, and this never ends.
In the end, you get a stack overflow.
A recursive function needs a way to know when the recursion ends. This is referred to as the base case. Without a base case, the recursion will keep happening until you run out of stack space, which typically causes your program to crash.
For your code, you want to get out when the argument is 0. So you need to to this:
int rev(int x)
{
int q,r;
static int p=0;
if (x == 0) return; // base case
p=p*10+(x%10);
r=x/10;
q=rev(r);
return(p);
}
Add any breaking condition in your code in you rev() function
if x == 0:
return 0

C: segmentation fault due to not freeing memory in somewhere else. how to free memory

I have a function as Follows:
double **E_min;
int *D_K;
double *prob;
char checker[] = "yes";
while(!strcmp(checker,"yes")){
.
.
.
E[I_indice][t] = ProcurementCost(Q[t+1][I_indice], c, k) + h*fmax(0,I[t])
+ p*fmin(0,I[t])
+ CalculateSigma(d_max, I_indice+Qt_DP, E_min, D_K, prob, t+1, Num_DK);
.
.
.
free(E_min)
free(D_K)
free(prob)
printf("Do you want to check another forecast? (yes/no)\n");
scanf("%s", &checker[0]);
} // this is for while loop
I have my segmentation fault in CalculateSigma function.
here is my calculate sigma function:
double CalculateSigma( int D_max, int insideSum, double **Emin,
int *D_K, double *probability, int insideTIME, int num_DK)
{
int counter;
double Sigma = 0;
for (counter = 0; counter < num_DK; counter++ )
{
Sigma += probability[counter]* Emin[insideSum- D_K[counter]][insideTIME];
}
return Sigma;
}
So here is the question.
When I run this program for the first time, it runs completely without any issue. but when it asks that if I want to give another number, it will give me a segmentation fault after getting into CalculateSigma function. I think the reason is the three pointers that I have in the function which are : Emin, D_K, Probability are not the same as my pointers in the main loop. so I have to free them. but if I free them I get a seg fault from the begining, because they are also somehow related.
So i got completely confused here. can someone tell me what should i do??
thanks
There are other issues with the code and/or it is incomplete. But, first things first.
Why do you have ?
free(E_min)
free(D_K)
free(prob)
if you intend to reuse the variables in the next loop iteration. Also, I don't see where they were first allocated. These are basic questions to be resolved, before proceeding further.

C program to find the n'th prime number-

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int prime(long long int);
long long int *arr; //array to hold n prime numbers
int main()
{
int i,count=4;;
long long int n;
scanf("%lli",&n);
arr=malloc(sizeof(long long int)*n);
arr[0]=2;
arr[1]=3;
arr[2]=5;
arr[3]=7;
if (n==1) printf("%lli",arr[0]);
else{ if (n==2) printf("%lli",arr[1]);
else{ if (n==3) printf("%lli",arr[2]);
else{ if (n==4) printf("%lli",arr[3]);
else
{
for(i=2;count<n;i++)
{
if(prime(6*i-1)) { /*As prime nos are always 6k+1 or
arr[count]=6*i-1; 6k-1fork>=2 I checked only for those*/
count++; }
if(prime(6*i+1)&&count<=n) {
arr[count]=6*i+1;
count++; }
}
printf("%lli",arr[count]);
}}}}
//free(arr);
return 0;
}
int prime(long long int x)
{
int j=1,flag=1;
while(arr[j]<=sqrt(x))
{
if (x%arr[j]==0)
{
flag=0;
break;
}
j++;
}
return flag;
}
The code is working only for n=1,2,3,4, i.e i=0,1,2,3 for which the values are explicitly given. For n=5 onwards it is giving 0 as O/P
There is some glitch related to the global dynamic array as free(arr) is giving core dump error.
Q: Is this the right way to declare a global dynamic array? What could be the problem in this code?
Thank You in advance.
If that is your actual code you have 4 bugs:
2 line comment scopes out a line of your code
the second if should check count < n not count <= n as if count == n you cannot write to arr[count]
You cannot print arr[count] only arr[count-1] which is probably what you mean
In the case where n is less than 4 you still set arr[1], arr[2] and arr[3] which may be out of bounds
It is of course also inefficient to call sqrt(x) in every loop iteration, potentially you should call it outside and there may be a potential rounding issue bug due to the way square roots are calculated, so you might prefer:
while( arr[j] * arr[j] < x )
It would be preferable not to make this global and to pass it into your function.
It would also be preferable to move the main loop logic of your program outside of main().
I'm surprised you say you program works for n=1, 2 and 3 as it looks like you are setting out of bounds.
Your counter goes beyond the size of the array. Specifically both conditions (6i-1 and 6i+1) are met for i=2, and therefore counter is incremented twice, resulting in using arr[5] where you only allocated 5 places in the array. This is because you check counter<=n and not counter
Not sure this could be also be the reason for free creating a core dump, but it is possible (because once corrupting the memory, free may access corrupted data).

Resources