what is the segmentation fault in this program - c

#include<stdio.h>
#include <stdlib.h>
int main()
{
int n,small=0,large=0,s,l,temp;
printf("this should work");
scanf("%d",&n);
// printf("%d",n);//
int a[n];
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
/* for(int i=0;i<n;i++)
printf("%d",a[i]);*/
small=a[0];
large=a[n-1];
for(int i=0;i<n;i++)
{
if(a[i]<small && i!=0)
{
small=a[i];
s=i;
}
if(a[i]>large && i!=n-1)
{
large=a[i];
l=i;
}
}
temp=a[s];
a[s]=a[l];
a[l]=a[s];
for(int i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
This is a simple program to swap the largest and smallest number in an array and print the new array.
When I tried to run this program I got a segmentation fault.
Usually, a segmentation fault occurs when we try to access an out of bound memory location.
So I added printf statements to find out where the error is.
But none print statements were executed. what is the error here ?

One problem is that you don't actually set s and l to anything unless you find an element that is smaller/larger than the current one.
That means (for example), if the first element is the smallest, s will be set to some arbitrary value and trying to index the array with it could be problematic.
To fix that, where to set small and large, you should also set:
s = 0;
l = n - 1;
In addition, your swap code is wrong and should be:
temp = a[s];
a[s] = a[l];
a[l] = temp;

You should initialize s and l to some value because when the if condition does not works their values will remain uninitialized garbage values. Hence, a[l] or a[s] will not work, since these indexes are undefined values. That is why you will get segmentation fault because you are accessing an undefined area of an array.
So, use random values within array range like s=0,l=0 to initialize the variables or you can add some flags to check if the conditions are working.
if (l != 0 && s != 0) {
temp=a[s];
a[s]=a[l];
a[l]=a[s];
}
Also, I think you are swapping the values so in the last line a[l]=temp instead of a[l]=a[s].
ideone link

You cannot declare an array based on a dynamic size, unless the compiler supports it and even then it is generally not portable.
int a[n]
you actually need to use malloc or calloc.
int *a;
a = (int *)malloc(n * sizeof(int)); or a = (int *)calloc(n, sizeof(int));

Related

Segmentation fault with Selection Sort recursive functions

For class I have to make a Selection Sort function recursively with no loops. I finally got it to compile with no errors, but now it just says "segmentation fault (core dumped)". I'm pretty new to C so please explain what this means. I'm assuming that there's a stack overflow, but I can't see where or how.
Here are my two functions involved in Selection Sort.
void CheckRemaining(int arr[], int minpos, int len, int j) {
if (j == len - 1) {
return;
}
if (arr[minpos] > arr[j]) {
minpos = j;
}
CheckRemaining(arr, minpos,len, j + 1); //j increments with each iteration
}
void SelectionSort(int arr[], int len) {
int i = 0;
int j;
int minpos;
minpos = i;
if (i == len - 2) {
return;
} else {
j = i;
CheckRemaining(arr, minpos,len, j);
swap(&arr[minpos], &arr[j]);
SelectionSort(&arr[i++], len); //The location in the array increments
}
}
int main() {
int i;
int len;
int arr[] = {5,7,3,2,9,4,10};
len = sizeof(arr)/sizeof(arr[0]);
SelectionSort(arr,len);
for ( i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
return 0;
}
Am I missing something big here?
You are most likely correct that you have a stack overflow, because the recursion will never end.
The problem is that you use the local variable i in the condition to terminate the recursion, but you forget that local variables are local for each call. Every time the SelectionSort is called, there will be a new i variable initialized to zero, so the recursion will never end.
SelectionSort(&arr[i++], len);
I think, it should not work for this code. The recursion will never end. Every time you are calling to SelectionSort() and initializing i with 0. So i will never be len-2. Each time this function is getting a different i.
int i=0;
You defined i as a local scope variable, meaning that every time is called, i=0 is taking effect, preventing you from ever having any i greater then 0, thus this condition:
if (i==len-2)
will never be true. Hence, you get an infinite loop.
By the way, to answer to you about the segfault, when you have a segmentation fault, it means that you wanna reach a "forbidden" memory area, for example (usual error in beginning) when you didn't malloc'd a string/tab and your loop's index is "too far" you want to access to a "forbidden" area then it segfault.

Segmentation Fault while initializing array in C

I am a very beginner in C. I went through the existing questions but could not understand because they involved strings and characters. Here is my little part of my code:
#define grid 32
int main (void)
{
int NU, NV, NP;
NU=(grid-1)*grid;
NV=grid*(grid-1);
NP=grid*grid;
double u[NU], uc[NU];
double v[NV], vc[NV];
double p[NP], pc[NP];
//Initialization
// Initializing u
for (i=0; i<(grid-1); i++)
{
for (j=0; j<(grid); j++)
{
int k=j*grid+i;
if (j==(grid-1))
{
u[k]=1.0;
}
else if (j==(grid-2) && i>0 && i<(grid-2))
{
u[k]=1.0;
}
else
{
u[k]=0.0;
}
}
}
// Initializing v
for (j=0; j<(grid-1); j++)
{
for (i=0; i<grid; i++)
{
int k=j*grid+i;
v[k]=0.0;
}
}
// Initializing p
for (j=0; j<grid; j++)
{
for (i=0; i<grid; i++)
{
int k=j*grid+i;
p[k]=1.0;
}
}
I am trying to initialize these arrays but instead getting segmentation fault.
Kindly help me with this.
This line is the problem:
int k=j*grid+i;
Its taking your array index out of bounds. When you access u[k] then you get a seg fault. Also, there is no need to use 2 loops to initialize a single dimensional array unless there is a specific logic you are trying to implement here which i am not aware of.
You defined
NU=(grid-1)*grid;
NV=grid*(grid-1);
NP=grid*grid;
Now let's see how far you are accesing the array elements in the loop.
for (i=0; i<(grid-1); i++)
{
for (j=0; j<(grid); j++)
{
int k=j*grid+i; // so in the max case k = (grid-1)*grid+grid-2 = grid*grid+2
... // and it is larger than NU so it will be accessing wrong memory
// memory region
}
}
Follow the same anlysis to make sure other array initialization does not exceed the boundary.
The only reason array initialization can result in a SEGFALT is by reading or writing to an element which does not exist.
The most common way to accomplish this is by using an index beyond the bounds of the array. In C, the lowest element is index 0 (zero) and the highest is N-1 where N is the number of elements declared for the array.
int array [5000];
array [-1] = 0; /* BAD */
array [5000] = 0; /* BAD */
Both of these are invalid accesses. They might SEGFAULT. They might change another variable's value. They might seem to do nothing. Or they might seem to work.

segfault when iterating over 2d array

I am trying to do a simple function which prints an array of a defined size. However, after the function prints the array, a seg fault occurs. This seg fault only occurs when boardSIZE is defined as equal to 19 or larger. Anything less then 19, and no segmentation fault occurs. Can anyone explain why this is, and/or suggest how I can perform a similar task of defining a global variable larger than 20 here without getting a seg fault?
#include <stdio.h>
#define boardSIZE 40
void printBoard(char [][boardSIZE]);
int main()
{
char board[boardSIZE][boardSIZE];
printBoard(board);
}
void printBoard(char board[boardSIZE][boardSIZE])
{
int i,j;
for (i=0;i<=boardSIZE;i++){
for (j=0;j<=boardSIZE;j++){
board[i][j]='X';
printf("%c",board[i][j]);
}
printf("\n");
}
}
Don't use <= in your loops. Use <. For an array of size n, valid indexes go from 0 to n-1. Thus, your loop is accessing out-of-bound positions.
Change your printBoard() function to:
void printBoard(char board[boardSIZE][boardSIZE])
{
int i,j;
for (i=0;i<boardSIZE;i++){
for (j=0;j<boardSIZE;j++){
board[i][j]='X';
printf("%c",board[i][j]);
}
printf("\n");
}
}
you blow the array bounds.
you allocated boardSIZE, this means the max index that is available is boardSIZE - 1 because the first index is 0 not 1. so change the <= to < in both for loops and the seg fault will resolve!
void printBoard(char board[boardSIZE][boardSIZE]) {
int i,j;
for (i = 0; i < boardSIZE; i++){
for (j = 0; j < boardSIZE; j++){
board[i][j] = 'X';
printf("%c",board[i][j]);
}
printf("\n");
}
I suggest you edit your title to something more suitable as this doesn't have anything to do with global variables

Segmentation Fault 11 with recursive function in C

I keep receiving a Segmentation Fault 11 for the following code. I believe it has something to do with recursion but I'm not entirely sure how. The method should take in an array, skip the odd values, and keep repeating until it has an array with only value left and returns that value.
Thanks!
#include <stdio.h>
int callTable(int table[], int size)
{
int i = 0;
int j = 0;
int cHeight = size / 2;
int cTable[cHeight];
while (i < size)
{
if (table[i] % 2 == 0)
{
cTable[j] = table[i];
j++;
}
i++;
}
if (size > 1)
return callTable(cTable, cHeight);
else
return cTable[0];
}
int main()
{
int tPass[100];
int i, answer;
for (i = 0; i < 100; i++)
tPass[i] = i + 1;
answer = callTable(tPass, sizeof(tPass) / sizeof(tPass[0]));
printf("%d\n", answer);
}
Do you want to skip the odd values or the odd indexes? You are currently skipping the odd values, so after you call callTable once, there are only even values left. Then, on the second call, you try to use an array of half the size to store the even values (which are all of them), so you try to store the entire array on another with half the size.
If you intended to skip the odd indexes, then change this line:
if (table[i]%2==0)
for this one:
if (i%2==0)
That runs fine and returns 1 (which is the number with index 0).

Array doesn't print in reverse in C using pointers

I am trying to make a program that takes 10 numbers as input and outputs them in reverse order using pointers in C.
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0;i<N;i++) {
scanf("%d",(array+(4*i))); //Works
}
for (j=N-1;j<0;j--) {
printf("%d",array[j]); //Doesn't print, using *(array+j*4) doesn't
//print also
}
printf("\n");
printf("%d\n",*(array)); //Works so scanf works
printf("%d\n",*(array+4)); //Works so scanf works
return 0;
}
I have tried a making a seperate function for the two for loops but still it doesn't work. I want to know WHY this for-loop doesn't print but the two printfs below it print.
EDIT:
My new code is
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0;i<N;i++) {
scanf("%d",(array+i)); //Works
}
for (j=N-1;j<0;j--) { //it is supposed to be j>=0 or j>0 WHY
printf("%d",array[j]); //Doesn't print, using *(array+j) doesn't
//print also
}
printf("\n");
printf("%d\n",*(array)); //Works so scanf works
printf("%d\n",*(array+1)); //Works so scanf works
return 0;
}
Thanks to all the posts, I have a better understanding of how indexing works in C now but the printf doesn't work still unless I change the for-loop conditions(see above). WHY doesn't it work with the initial conditions but with the latter conditions.
Whoa!
This:
scanf("%d",(array+(4*i))); //Works
is very wrong and is overwriting memory! Why are you multiplying the index? You don't need to do that, C can index by itself. It should just be:
scanf("%d", &array[i]);
You want the address of the i:th array member, so say that, don't beat around the bush with strange multiplications.
If you really want to be "using pointers", as mentioned in a comment, you can do so:
scanf("%d", array + i);
This works since array is a pointer to the first element of the array, and adding i to is a fully valid use of pointer arithmetic; C will compute the proper pointer, knowing the size of each int in the array.
Your array consists of 10 elements with type int (obviously). In expression array + i variable i is not an offset in bytes. It is an index of element. So when you read it like you do (scanf("%d",(array+(4*i)))) you basicly read array[0], array[4], array[8], array[12] (we're out of array bounds here already, it causes memory corruption and might cause crashes), etc. Elements array[1],[2],[3],[5], etc. are uninitialized. That's why your code doesn't work :)
UPDATE:
And #shilong-liu's note about array indices is important, too. I didn't notice it.
for (j=N-1;j<0;j--) {
printf("%d",array[j]); //Doesn't print, using *(array+j*4)
}
the for loop is not right. The correct one is that
for (j = N - 1; j > 0; j--)
I guess since the pointer used is of type int, you assume that you have to multiply i by 4 because depending on the compiler int is 4 bytes. I guess if you really care only about the output, then you could do it the way you did with reverse iteration.
What you have to do has been already mentioned by the others so I will give you my solution for actually swapping the pointers memory wise and you could choose from the given solutions:
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0; i<N; i++) {
scanf("%d", (array + i));
}
for (left = 0; left < N / 2; left++)
{
int right = N - left - 1;
int temporary = array[left];
array[left] = array[right];
array[right] = temporary;
}
for (i=0; i<N; i++) {
printf("%d", (array + i));
}
return 0;
}
I have been programming for algorithmic contests so you could trust me.

Resources