I cannot understand how this code is causing a segfault when I run it, can anyone help me understand what is going on??
#include <stdio.h>
unsigned long long factorial(unsigned long long x, unsigned long long amt)
{
if (x == 1ULL) return amt;
else return factorial(x-1ULL, amt*x);
}
int main(int argc, char *argv[])
{
for (unsigned long long i = 0; i < 10ULL ;i++) {
printf("%llu\n", factorial(i, 1ULL));
}
}
First, the segfaults are not necessarily caused be invalid pointer dereference. In this case, it is actually caused by infinite recursion and eventual running out of stack space. Why? The essential requirement of a recursion function is it has to finish and terminate the recursion at some state, if you look carefully your code, in function factorial, if x is 0, then the recursion will become endless and eventually crash your program. You can fix this by change the terminate condition to:
if (x <= 1ULL) return amt;
In the orginal code :
if (x == 1ULL) return amt;
is meant to be the exit condition for this recursive function factorial. However when a value of zero is passed to the function and given that the type of x is unsigned long long, first recursive call to the function factorial with the parameter x-1ULL would set the value of x to very large value (18446744073709551615 is what I got here). Successive recursive calls to factorial will gradually deplete the stack space allocated for the program to the point where you get a segmentation fault.
You should have been doing this:
#include <stdio.h>
unsigned long long factorial(unsigned long long x, unsigned long long amt)
{
if (x == 0ULL) // Changed the exit condition, see Reference [1]
return amt; // Bear in mind that the initial value for amt you passed is 1
amt*=x; // See Reference [2]
return factorial(x-1ULL, amt);
}
int main(int argc, char *argv[]) {
for (unsigned long long i = 0; i < 10ULL ;i++) {
printf("%llu\n", factorial(i, 1ULL));
}
}
References
The idea of the factorial (in simple terms) is used to compute the number of permutations (combinations) of arranging a set of n numbers. It can be said that an empty set can only be ordered one way, so 0! = 1. Check this.
I feel this is more readable than factorial(x-1ULL, amt*x)
Note
The ULL suffixes are redundant here and may be removed altogether.
Related
I tried to write a code to calculate how many 1 are there in a number's binary form. This is my code:
#include <stdio.h>
#include <math.h>
static int num = 0;
void binary(int target){
int n = 0;
int a = 1;
if(target != 0){
while(target >= a ){
n++;
a = pow(2, n);
}
a = pow(2, n-1);
num++;
binary(target - a);
}
}
int main() {
int target = 0;
scanf("%d", &target);
binary(target);
printf("%d",num);
return 0;
}
However, this shows segmentation fault when I run it. I don't know where has the code tried to access memories that are not allowed. I figured it might have something to do with the recursion in the binary function. Can anyone tell me what have caused the segmentation fault here? Thank you so much. I really can't understand segfaults :(
As mentioned in the comments, pow is not a good candiate here due to its signature:
double pow(double x, double y);
so any place that you are using pow, you are implicitly using floating point numbers. I was able to cause a segfault with the input 1<<31 which is the value -2147483648. This will cause your loop to terminate with n=0, a=1. You then set a = pow(2, -1), but since a is an integer, this gets floored down to just 0. You then recurse with binary(target - 0) which might as well just be binary(target) again, hence you have an infinite call with no termination.
I'll also leave as a note that recursion for this type of problem is probably not the right tool, unless your goal is to learn about recursion. There is a much more concise and reliable method via a loop and the & operator. I would also suggest using unsigned values to avoid issues like this with negative terms.
I am trying to read/write hexadecimals into a 2D integer array for my program, but there are issues with some hexadecimals.
When I input 272cf50 it accurately turns into 41078608 in the array and I have no problems.
But when I input ffff0000000 it turns into -268435456 instead of its decimal equivalent: 17591917608960.
Because of this when I try to check if ffff0000000 already exists in the array it says it doesn't even though I wrote it into the array. I am confused about why this is happening and how I can fix it.
This is the code:
bool inCache(unsigned long addy, unsigned long blockid, unsigned long setidx, int size, int** cache, int lps){
//find set index
//find easier way
int i=0;
while(cache[i][0]!=setidx){
i++;
}
//check if set contains blockid
for(int j=0; j<lps; j++){
if(cache[i+j][2]==1 && cache[i+j][1]==blockid){
return true;
}
}
//not in cache
return false;
}
void read(unsigned long addy, unsigned long blockid, unsigned long setidx, int size, int** cache, int lps){
unsigned long x = blockid;
bool e = inCache(addy,blockid,setidx,size,cache,lps);
if(e==true){
ch++;
}else{
cm++;
mr++;
//set x in cache
newWrite(addy,x,setidx,size,cache,lps);
}
}
void newWrite(unsigned long addy, unsigned long blockid, unsigned long setidx, int size, int** cache, int lps){
//check if already loaded in cache
bool e = inCache(addy,blockid,setidx,size,cache,lps);
if(e!=true){
//load the block into chosen cache line
//find the setidx
int i=0;
while(cache[i][0]!=setidx){
i++;
}
//go thru set and put into first available cacheline
for(int j=0; j<lps; j++){
if(cache[i+j][2]==0){
cache[i+j][2]=1;
cache[i+j][1]=blockid;
break;
}
}
//if all cachelines are full, put into least recent cacheline
cache[i][1]=blockid;
}
}
This is the specific example:
0x1: R 0xffff0000000
0x2: R 0xffff0000000
In my particular example, for the first line the read function gets called and since the value is not in the array(cache) it calls the newWrite funciton to add it to the array. When it is added to the cache is when it converts to -268435456. Then, for the second line when the read function checks if the value is in the array it returns false instead of true.
This is a prime example of an integer overflow. Precisely what happened, was that the inputted number was interpreted as two’s complement. The number was so long that the sign bit got flipped. Indeed,
0xFFFF0000000 - 2⁴⁴ = -268435456
which is where that mysterious number came from.
Surely the best way to manage this situation is to keep care that the variables used can hold numbers that big, or to reject too large values.
EDIT with more information
The code shows that the array’s signature is int **. This should be unsigned too in order to make the comparison to work. The following code demonstrates the problem:
#include <stdio.h>
int main(void)
{
int a = 0xffff0000000;
unsigned long b = 0xffff0000000;
printf("%d\n",a==b);
/* the number zero (meaning "false") is printed */
}
I was trying to implement this problem from SPOJ: http://www.spoj.com/problems/COINS/ using memoization but I keep getting Runtime error and cant figure out why. Here is my code:
#include<stdio.h>
long long int max(long long int a,long long int b)
{
if(a >= b)
return a;
else
return b;
}
long long int dp[100000];
long long solve(long long int n)
{
long long ans;
if(n<=50000)
return dp[n];
else
ans=(n,solve(n/2)+solve(n/3)+solve(n/4));
return ans;
}
int main()
{
long long int n;
int t;
for(int i = 0;i <=50000;i++)
{
dp[i] = max(i,dp[i/2] + dp[i/3] + dp[i/4]);
}
while((scanf("%d",&t))>0)
printf("%lld",solve(n));
return 0;
}
Here are a few problems:
In solve, you have ans = (n,solve(n/2)...); The leading n has no effect. Did you intend this to be an argument list to max? If so, you need to add max. Otherwise it's just a comma expression and you might as well remove the leading n.
In main, your initialization of dp has a problem. Consider the first pass through the loop, when i is 0. In this case, i/2 etc. will also be zero, hence those dp values will be undefined. Try setting dp[0] explicitly, outside of the loop, and then start your loop at index 1 instead.
When printing the solution in main, you probably want to add newling \n to the end of your printf format string.
As noted by others, when calling solve from main, you are passing n rather than t.
The problem is most likely due to this:
while((scanf("%d",&t))>0)
printf("%lld",solve(n));
You are reading t but passing n which is uninitialized. You probably want to pass t to solve():
while((scanf("%d",&t))>0)
printf("%lld",solve(t));
Reason you get Runtime Error
while((scanf("%d",&t))>0)
printf("%lld",solve(n));
Here, You get input in variable t but pass variable n to solve function. Use variable t or n for both case. It will solve your problem.
My job is to prove fermats theory incorrect using c. so what i did was have nested loops, its pretty easy to read.
here is the code:
#include <stdio.h>
#include <math.h>
quadtest(unsigned long long int a, unsigned long long int b, unsigned long long int c, unsigned int n)
{
if ((pow(a,n)+pow(b,n))==pow(c,n))
return 1;
else
return 0;
}
main()
{
unsigned long long int a;
unsigned long long int b;
unsigned long long int c;
unsigned int n;
//a=1; b=1; c=1; n=1;
for(n=2; n<100; n++)
{
printf("\nn=%d",n);
for(c=1; c<500; c++)
{
printf("\ntrying now c=%d and n=%d",c,n);
for(b=1; b<500; b++)
{
if (quadtest(a,b,c,n)) break;
//printf("\nb=%d, n=%d",b,n);
}
for(a=1; a<500; a++)
{
if (quadtest(a,b,c,n)) break;
//printf("\na=%d, n=%d",a,n);
}
}
printf("\nthe right values to prove fermats theory wrong are n=%d,c=%d,b=%d,a=%d",n,c,b,a);
}
}
after being compiled, im getting "trying c=random number, n=0. n always equals 0 for some reason even though its never supposed to be 0.
im also getting something like "the right values to prove fermats theory wrong are n=99,c=500,b=0,a=500"
which once again, neither a, b, c, or n are supposed to be 0. not sure what the problem is
There are two clear problems with your code:
You define several variables, and each is initialised except for a. You call a function using a uninitialised. This is undefined behaviour and could explain your problem.
Secondly, you are using the incorrect specifier in printf. %d is used for int; %llu is for unsigned long long. Using the wrong specifier can lead to incorrect values being output.
I've very recently started to learn C, so I realize my question is very basic, but any help would be very much appreciated.
I'm trying to get the function fact to return the res value to main, but when I print out the result in main I just get 0. By inserting some print statements I can see that res is calculating correctly in the fact routine but the result is not returning correctly to main.
I'm sure I'm missing something very basic here.
Thanks
#include <stdio.h>
unsigned long fact (int n){
unsigned long res = 1;
while ( n >= 0 )
{
res *= n;
n--;
}
return res;
}
int main (void){
int n;
unsigned long res;
printf("Insert number:\n");
scanf("%d", &n );
res = fact (n);
printf("The factorial number is %lu", res);
return 0;
}
Your loop condition is n >= 0, which means that res will be multipled by 0 before the function returns. Thus the result will always be 0.
You loop condition is wrong. The last run of while (n>=0) will have n=0. Multiplying res by this will reset it to 0.
You can fix this by changing your loop to while (n > 1)
For future reference, you could investigate problems like this using a debugger (e.g. GDB or visual studio express). Or by adding printf statements to your code to trace the flow and see how the value of res changed through the program.