SIGSEGV error keeps showing up - c

this error keeps on appearing for every program i try to submit on spoj.pl
In the given code i need to find prime numbers between m - n for t no. of test cases .
problem statement:http://www.spoj.com/problems/PRIME1/
the same error is appearing ..
can anyone plss tell me why this error shows up again nd again ..
here's my code
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
int main()
{
int t;
scanf("%d",&t);
int *m,*n;
m=(int *)malloc(sizeof(int)*t);
n=(int *)malloc(sizeof(int)*t);
int i=0;
while(i<t)
{
scanf("%d%d",(m+i),(n+i));
i++;
}
i=0;
while(i<t)
{
long long int *list,j,k;
list=((long long int*)malloc(sizeof(long long int)*(n[i]+1)));
list[0]=list[1]=0;
for(j=2;j<=*(n+i);j++)
{
*(list+j)=1;
}
float l=sqrt(*(n+i)+1);
//int l=sqrt(*(n+i)+1);
for(j=2;j<=l;j++)
{
if(*(list+j)==1)
{
//printf("\n%ld",j);
for(k=j*j;k<=*(n+i);k=k+j)
*(list+k)=0;
}
}
for(j=m[i];j<=n[i];j++)
{
if(*(list+j)==1)
{
printf("\n%ld",j);
}
}
printf("\n");
free(list);
i++;
}
free(m);
free(n);
return 0;
}

First -- you should not cast malloc -- it can cause unexpected errors.
Second, there's no validation that you allocated the memory you need. There are three different places you're asking for memory and never look to see if malloc returned a NULL result... if t and/or (n[i]+1) is sufficiently large, malloc() may be unable to get a chunk of memory big enough to satisfy the request, in which case you're trying to assign to a NULL pointer and you get a SIGSEGV -- there's a hint given in the description of the problem
Warning: large Input/Output data, be careful with certain languages
(though most should be OK if the algorithm is well designed)

Seems to work fine on my computer, except for the warning about using %ld (%lld should be used). I can only obtain a SIGSEGV error when putting 0 as a value for n[i]. Could you indicate what values you used to generate that error?
Edit :
You are testing for the values "1 888888888 1000000000".
Your computer simply can't allocate an array of such size. You are asking an array of size 1000000001 in your memory. That amounts to about 8GB (since a long long int as about 8B, at least on my computer), which is pretty much undoable for your computer.

Related

Limit for memory allocation to an array on stack in C?

I don't know how to ask this question as it was little confusing to me. i was having a problem with this code
#include <stdio.h>
#include <stdlib.h>
#define ull unsigned long long
#define SIZE 1000000001
#define min(a,b) ((a<b?a:b))
#define max(a,b) ((a>b?a:b))
int solve(void) {
// unsigned *count = malloc(sizeof(unsigned) * SIZE);
int k;
scanf("%d", &k);
unsigned count[SIZE];
for (ull i = 0; i < SIZE; i++){
count[i] = 0;
}
return 0;
}
int main(void){
unsigned t;
if (scanf("%u", &t) != 1) return 1;
while (t-- > 0){
if (solve() != 0) return 1;
}
}
This code for me is giving segfault.
What my observation is
it is running fine until it is in solve function.
on calling solve function it is giving segfault.
It has nothing to do with scanf("%d", &k) as by removing this line gives the same error
But if we decrease the SIZE value it will run fine.
Other thing which i can do is instead of creating an array on stack i can use heap and this is working fine.
If i only declare array count in solve function instead of taking k as input and initializing all the values of array count to 0. i am not getting any segfault
So i have some questions regarding this.
Is this due to memory limitation to array or because of memory limitation for a stack frame for the function solve (or possibly another reason which i can't find).
If this is due to any kind of memory limitation than isn't it is too low for a program?
How compiler checks for such errors as adding any kind of print statement won't run before array declaration as i am getting segfault when program reaches solve. So compiler somehow knows that their is a problem with code without even getting there.
and specifically for the 6th point, as per my knowledge when declaring array it reserves memory for the array. So by initializing it i am doing nothing which will increase the size of array. So why i am not getting any kind of error when declaring array while i am getting segfault when i am initializing all those values in array
Maybe i am seeing it in totally wrong way but this is how i think it is, So please if you know any reason for this please answer me about that too
It depends on your operating system. On Windows, the typical maximum size for a stack is 1MB, whereas it is 8MB on a typical modern Linux, although those values are adjustable in various ways.
For me it's working properly check with other platform or other system.

SIGSEGV in C error

I always get an SIGSEGV error whenever i am dynamically initializing arrays in C. Please tell me what am I doing wrong all the time?
The code works fine on TurboC but it gives SIGSEGV on an online judge which uses GCC.
Programming Problem
My code:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
long n,h,i,crane=0,box=0,temp=0;
long *comm;
scanf("%ld %ld",&n,&h);
long *a = (long*)malloc(n*sizeof(long));
for(i=0;i<n;i++)
scanf("%ld",&a[i]);
scanf("%ld",&comm[0]);
i=0;
while(comm[i]!=0)
{
i++;
scanf("%ld",&comm[i]);
}
for(i=0;comm[i]!=0;i++)
{
if(comm[i]==3)
box=1;
if(comm[i]==4 && box==1)
{
a[crane]=(a[crane]+1);
temp=0;
}
if(box==1 && (comm[i]==1 || comm[i]==2) && temp==0)
{
a[crane]=(a[crane]-1);
temp=1;
}
if(crane!=0 && comm[i]==1)
crane--;
if(comm[i]==2)
crane++;
if(comm[i]==0)
break;
}
for(i=0;i<n;i++)
printf("%ld ",a[i]);
free(a);
free(comm);
return 0;
}
For a start, nowhere in that code are you actually allocating memory for comm to point to. You apparently know this is required since you've done something similar for a and you free both a and comm at the end.
You need to malloc the memory for comm to point to, before using it. For example, if you wanted that to depend on the second value input (h, probable since it's not used anywhere else), you would need to add in:
comm = malloc(h*sizeof(long));
after the first scanf, noting that I don't cast the return value - you shouldn't do that in C.
If you don't know how big comm should be before using it, the usual way to handle that is to allocate a certain number of elements (the capacity) and keep track of how many you've used (the size). Each time when your size is about to exceed your capacity, use realloc to get more space.
The following (C-like) pseudo-code shows how to do this, starting with an empty array and expanding it by thirty elements each time more space is needed:
comm = NULL
capacity = 0
size = 0
for each value in input():
if size == capacity:
capacity += 30
comm = realloc (comm, capacity), exit if error
comm[size++] = value
Note that, on loop exit, size is the indicator of how many elements are in the array, despite the fact there may be more capacity.
And, as an aside, you should always assume that calls subject to failure (such as scanf and malloc) will fail at some point. In other words, check the return values.

SIGSEGV Error in short C code

So, as someone who is fairly new to C, I came across my first SIGSEGV Error.
It appeared in a short C program that is meant to be a "guess the number" game. It consists of a self-defined function that compares two numbers and a do-while loop with an input inside it.
The start and the do-while loop:
#include<stdio.h>
int checkNum(int num1, int num2); //See below for explanation
int main(void) {
int input=0, rand=3; //"Random" number has fixed value for testing
do {
printf("Enter number from 0-10: "); //There is not actual range yet
scanf("%d",input); //Get input
} while(checkNum(input, rand)); //Checks if difference != 0
}
The function for comparing:
//Function for comparing input with "random" number
int checkNum(int num1,int num2) { //The two numbers that get compared; First one: input, Second one: "random" rumber
if(num1==num2) {
printf("Correct. The random number was %d",num2);
} else if(num1<num2) {
printf("Wrong. The random number is bigger.");
} else if(num1>num2) {
printf("Wrong. The random number is smaller.");
}
return num2-num1; //Return the difference, leads to 0 if equal
}
I suspect the error to be in the function, caused by a missing use of a pointer, but as far as I understand pointers, they don't seem necessary here: I don't change a single variable in the function, and the return only subtracts two values (which are given I assume).
I hope my error isn't too stupid, and I'd like to thank everyone who can help or tries to.
(I can post my processor values, altough I am not sure if that will help; If any more information is needed for debugging, please tell me)
This:
scanf("%d",input); //Get input
should be:
scanf("%d",&input); //Get input
^^^
Pro tip: always compile with warnings enabled (e.g. gcc -Wall ...) and the compiler will happily point out simple mistakes such as this, saving you a lot of time and grief.

Segmentation error in c program

I am getting segmentation error when trying to do this simple c sorting program
I am a novice in C language . And can you please explain me why i am getting segmentation error
#include<stdio.h>
int main(void)
{
int prev,next,result,total_number;
int i,j=1,b;
int a[i];
printf("Number of values to be entered");
scanf("%d",total_number);
printf(" enter the values \n");
for(i=0;i<=total_number-1;i++)
{
printf(" enter the values \n");
scanf("%d",a[i]);
}
for(i=0;i<=total_number-2;i++)
{
for(j=1;j<=total_number-1;j++)
{
if(a[i]>a[j])
{
b=a[i];
a[i]=a[j];
a[j]=b;
}
else
{
break;
}
}
}
for(i=0;i<total_number-1;i++)
{
printf("The numbers are %d",a[i]);
}
}
The segmentation fault is caused by this line:
scanf("%d",total_number);
You're missing the address of (&) operator, it should be like this:
scanf("%d",&total_number);
The operator is also missing in this line:
scanf("%d",a[i]);
You can find more details on scanf in the glibc manual:
Another area of difference between scanf and printf is that you must remember to supply pointers rather than immediate values as the optional arguments to scanf; the values that are read are stored in the objects that the pointers point to. Even experienced programmers tend to forget this occasionally, so if your program is getting strange errors that seem to be related to scanf, you might want to double-check this.
But there are other subtle errors in your code, too: the fact the int i in array[i] is not initialized leads to undefined behaviour i.e., anything could happen. You can use malloc to allocate space for the array, but a simple reordering could be enough:
scanf("%d",&total_number);
int a[total_number];
Uses user input to allocate the array.
Lastly, it seems like you're trying to implement an insertion sort algorithm, but the logic is slightly flawed: even correcting the bugs in the code the input
1 3 5 0
gets "ordered" to
1 5 3 0
But I don't know what you were trying to implement. In case you were actually trying to implement insertion sort, you could use the pseucode from the insertion sort wiki article to get an idea of what's missing in your implementation.
int a[i]; is creating an array of arbitrary size since i is not initialized.
Instead, you can dynamically create the equivalent of an array of int once you know total_number.
int* a;
. . . snip . . .
/* once you know total_number */
a = (int*) malloc(total_number, sizeof(int));
/* you can use a with array notation as long as you stay in bounds */
a[i] = something;
/* don't forget to free a when you are done */
free(a);

Bus Error in C for Loop

I have a toy cipher program which is encountering a bus error when given a very long key (I'm using 961168601842738797 to reproduce it), which perplexes me. When I commented out sections to isolate the error, I found it was being caused by this innocent-looking for loop in my Sieve of Eratosthenes.
unsigned long i;
int candidatePrimes[CANDIDATE_PRIMES];
// CANDIDATE_PRIMES is a macro which sets the length of the array to
// two less than the upper bound of the sieve. (2 being the first prime
// and the lower bound.)
for (i=0;i<CANDIDATE_PRIMES;i++)
{
printf("i: %d\n", i); // does not print; bus error occurs first
//candidatePrimes[i] = PRIME;
}
At times this has been a segmentation fault rather than a bus error.
Can anyone help me to understand what is happening and how I can fix it/avoid it in the future?
Thanks in advance!
PS
The full code is available here:
http://pastebin.com/GNEsg8eb
I would say your VLA is too large for your stack, leading to undefined behaviour.
Better to allocate the array dynamically:
int *candidatePrimes = malloc(CANDIDATE_PRIMES * sizeof(int));
And don't forget to free before returning.
If this is Eratosthenes Sieve, then the array is really just flags. It's wasteful to use int if it's just going to hold 0 or 1. At least use char (for speed), or condense to a bit array (for minimal storage).
The problem is that you're blowing the stack away.
unsigned long i;
int candidatePrimes[CANDIDATE_PRIMES];
If CANDIDATE_PRIMES is large, this alters the stack pointer by a massive amount. But it doesn't touch the memory, it just adjusts the stack pointer by a very large amount.
for (i=0;i<CANDIDATE_PRIMES;i++)
{
This adjusts "i" which is way back in the good area of the stack, and sets it to zero. Checks that it's < CANDIDATE_PRIMES, which it is, and so performs the first iteration.
printf("i: %d\n", i); // does not print; bus error occurs first
This attempts to put the parameters for "printf" onto the bottom of the stack. BOOM. Invalid memory location.
What value does CANDIDATE_PRIMES have?
And, do you actually want to store all the primes you're testing or only those that pass? What is the purpose of storing the values 0 thru CANDIDATE_PRIMES sequentially in an array???
If what you just wanted to store the primes, you should use a dynamic allocation and grow it as needed.
size_t g_numSlots = 0;
size_t g_numPrimes = 0;
unsigned long* g_primes = NULL;
void addPrime(unsigned long prime) {
unsigned long* newPrimes;
if (g_numPrimes >= g_numSlots) {
g_numSlots += 256;
newPrimes = realloc(g_primes, g_numSlots * sizeof(unsigned long));
if (newPrimes == NULL) {
die(gracefully);
}
g_primes = newPrimes;
}
g_primes[g_numPrimes++] = prime;
}

Resources