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);
Related
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.
I have been attempting to wrap my head around an idea that I am certain is possible, I just am not sure if I am going about it in the right way. My intention is to create an array and then fill it with as many values as the user wants. However my goal is to not use any defined value per se. I would like to be able to continue increasing it the amount of values it can contain indefinitely.
This is the test code I have been using to try and figure this out:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i;
int Up;
int Ary[0];
printf("Please enter the number of integers you want to input: ");
scanf("%d", &Up);
for(i = 0; i < Up; i++)
{
printf("Please enter a number: ");
Ary[i] = (int) malloc(sizeof(int));
scanf("%d", &Ary[i]);
}
for(i = 0; i < Up; i++)
{
printf("%d ", Ary[i]);
if(i % 10 == 0)
{
printf("\n");
}
}
return 0;
}
This may be a poor way of attempting to figure this out and I may also be doing this is a completely wrong way; However I get a segmentation fault sometimes. If I use small values such as only entering 4 or 5 values it works fine, however if I enter 10 values it gives me a segmentation fault. If I enter 50 values, it lets me enter all 50 but gives me a segmentation fault after printing out the 41st value.
The code itself is simply a means to an end. Ultimately what I would like to know is how I can set up an array of anything that can have values added to it indefinitely while retaining previous values using dynamic memory allocation?
PS. I hope this defines my question well enough, however if it does not I would like to refine my question so it is more clear. Please make a comment if this is unclear and why.
This isn't going to work:
int Ary[0];
You've made an array with no elements; the only valid use of such an array is to take its address, but you can't index into it as you have done.
Instead, you should make a pointer to what will later be allocated as an array:
int *Ary;
Then when you know how many integers you want:
Ary = malloc(Up * sizeof(int));
Now you can do Ary[index] for any index from 0 to (Up-1). If you later want to enlarge the array, you can use realloc() (many tutorials online for that).
You need to use dynamic allocation, what you are doing right now is static allocation, you need to learn how to use malloc and free.
So keep in mind that what you want to do is not "efficient" but can definitely be done as a learning exercise to learn how to make such a container.
What you need to do is allocate the amount of memory needed to contain the amount of values currently in your array +1 more value every time you want to "add" a new value to your array, for example: malloc(sizeof(int)*(<current_number_of_values>+1)).
I say "add" in quotes because what you will have to do is actually allocate memory for a brand new array every time and copy over your old values plus the new value the user enters and then free your old array to avoid memory leaks.
There are STL containers that do this internally but much more efficiently but I assume you are doing this to learn and not use your own containers for anything serious.
This question already has answers here:
segmentation fault using scanf with integer
(2 answers)
Closed 7 years ago.
Why this question is not duplicate?
The problem can't be at scanf, as it is given by the hackerrank and I can't modify the code! Also, test cases are automated, given by hackerrank. We can trust them with input reading. There is some bug in my logic of finding two elements in array, couldn't find it though :|
Note: I can't modify main method, as mentioned earlier. Re-iterating it. Why can't I modify? It is because the method is given by the portal. I can't change it. It reads the input and calls my method through some automated scripts, I've no control over it. So, please don't tell me to modify main method.
I was trying some practice problems in hackerrank in C language and some of the test cases started throwing Segmentation fault for following problem. I've tried understanding it for more than 2 hours now and couldn't think of any test case which will throw segmentation fault. I'm stuck :|
Problem statement:
Given an array and a number. Find if there are 2 elements in array, whose sum is equal to given number. If number are present return 1, otherwise 0.
pretty easy, huh? I thought the same and coded it as follows,
int compFunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int isSumPossible(int a[], int L, int N ){
/*L: Length of the array */
if(a==NULL) return 0;
if(L<=1) return 0;
int left=0, right=L-1;
qsort(a,L,sizeof(int),compFunc);
while(left<right)
{
if(a[left]+a[right]==N) return 1;
else if(a[left]+a[right]<N) left++;
else right--;
}
return 0;
}
int main() //given by hackerrank, I can't modify main method
{
int N; scanf("%d", &N); //fixed &N - it was correctly given in code, I missed it while typing it here.
int a[100004], i=0;
//read input into array a, based on N
int x;scanf("%d", &x); //fixed &x - it was correctly given in code, I missed it while typing it here.
printf("%d", isSumPossible(a,N,x));
}
Please assume all the header files required are included. Now, when I ran the code, most of the test cases passed and for some test cases they showed Segmentation fault. Unfortunately test cases aren't visible to me :|. I've gone through my code more than 10 times & I don't understand in which scenario I would get Segmentaion fault. Can anyone help me in understand which scenario am I missing in my code and why do I see segmentation fault?
The problem is in the scanfs in the main part of the code.
If you look at documentation the function description even says:
Reads data from stdin and stores them according to the parameter format into the locations pointed by the additional arguments.
This means you must give it a memory address to write data to. By adding & to both of your integer variables in your main the problem is solved.
int main()
{
int N; scanf("%d", &N);
int a[100004], i=0;
//read input into array a, based on N
int x;scanf("%d", &x);
printf("%d", isSumPossible(a,N,x));
}
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.
I came across this piece of code today while tutoring some students in a C programming language course.
The exercise asked to implement two functions. The first one scans input from a user and the second displays what has been previously scanned.
The code I came across is the following:
#include <stdio.h>
void myInput(int i,int n)
{
int cpt;
int tab[n];
for ( cpt=0; cpt<n; cpt++)
{
printf("Enter a number :");
scanf("%d",&i);
tab[cpt]=i;
}
}
void myDisp (int n)
{
int tab[n];
int cpt;
for ( cpt=0; cpt <n; cpt++)
{
printf("%d ", tab[cpt]);
}
}
int main()
{
int n; int i;
printf(" Entrer the numbers of elements you want: \n");
scanf("%d \n",&n);
int tab[n];
myInput(i,n);
myDisp(n);
}
Although this code is full of inconsistencies, it does actually work under gcc 4.4.3: it displays the numbers that have been input!!!!!!
Does anyone understands how come these code works?
Thanks very much
If that works, it's through sheer dumb luck. What is printed in myDisp is uninitialized stack, which may or may not contain the data that was put into similarly named variables in myInput. Related reading
Here's an easy way to break it with do-nothing code:
void myInput(int i,int n)
{
// Add some variables to mess up the stack positioning.
int breaker;
int cpt;
int stomper;
int tab[n];
int smasher;
for ( cpt=0; cpt<n; cpt++)
{
printf("Enter a number :");
scanf("%d",&i);
tab[cpt]=i;
}
// Trick the compiler into thinking these variables do something.
breaker = 1;
smasher = 3 * breaker;
stomper = smasher + breaker;
breaker = stomper * smasher;
}
Another way to break it would be to put a function call (say, to printf) between the calls to myInput and myDisp.
It doesn't work, at least not consistently. Granted I have gcc 4.4.4 not 4.4.3
$ ./a.out
Entrer the numbers of elements you want:
5
2
Enter a number :Enter a number :4
Enter a number :1
Enter a number :2
Enter a number :3
2 4 1 134514562 3
Moral of the story is when you access uninitialized memory, anything can happen, including the appearance of working.
Since the two arrays are completely separate it really should not work. If it does it's just because they ended up in the same location in memory.
Probably it works because the memory location of the tab local to myInput e myDisp happens to be (almost?) the same.
It doesn't sound so weird to me: myInput and myDisp have almost the same signature (they differ for just one int parameter); even in the worst case scenario the locations on the stack referred by tab in the two functions would be still correctly aligned and shifted at most by two ints (i and cpt in myInput).
It appears the program is accessing the same memory location for every array int tab[n] you declared but, as mentioned, it should not work.
But I think what's happening here is something like: you are allocating tab[] inside main(), let's say, under the address 0x00000001 (take it as an example only). The array have n integers but no values at all.
Then you go into myInput(), declare the array again (same size), in other address, like 0x001F0000, and then set the values, one by one.
So, when the function terminates, it frees the allocated memory of its variables, so your array does not exist anymore.
But wait, this is C, so when you free the memory, you only tells the heap (or the memory allocator, in general) that the addresses can be used again. You do NOT exactly remove the values from memory.
Then you call myDisp() and declare your array again. It appears the memory you just requested has higher priority and then it is somewhat given again to your program. So your array is again instanciated and on the same address.
So, even if you did not fill it with values, the memory is read (as it is always valid in C) and the values are still there.
Oh, and the array declared inside main()? Nothing happens to that. Try to print its values and I bet you'll not have the correct ones.
That is my guess.
EDIT: Just to see things happening: try to declare another array after tab (do not rename tab), say tab2, same length, and use it to put your values instead of tab, then let the program run again :)