Trying to access array element in loop causes segmentation fault, why? - c

I am trying to create a two dimensional array, which has either 1 or 0 randomly assigned to each coordinate. It works just fine until it gets to the coordinates [20][3]. After that it just throws out "segmentation fault 11".
I am absolutely clueless how or why. Especially since I can create a matrix with 200 * 200 for instance but it still gets the same Problem only at the coordinates [200][3]. So it is somehow always the third y coordinate in the last x coordinate where the error occurs.
#include <stdio.h>
#include <stdlib.h>
int main() {
int x, y, i, j ;
x = 20;
y = 20;
int grid [x][y];
for ( i = 0; i <= x; i++) {
for ( j = 0; j <= y; j++) {
grid[i][j] = rand() % 2 ;
printf("grid [%d][%d]: %d\n", i, j, grid[i][j]);
}
}
return 0;
}

C uses 0-based indexing for arrays. So, for an array defined as
int grid [x][y]
looping for
for ( i = 0; i <= x; i++)
for ( j = 0; j <= y; j++)
if off-by-one. (Note the <= part).
to elaborate, for an array of dimension p, the valid indexes are 0 to p-1, inclusive.
You should change your loop conditions as i < x and j < y to stay withing the bounds. Accessing out of bound memory causes undefined behavior.
That said,
int main() should be int main(void), at least, to conform to C standards for hosted environments.
There is no need to make grid as VLA here. If the dimensions are already known, better approach is to use a compile-time constant (#define) to generate the array dimensions.

You're running past the bounds of the array. That's undefined behaviour in C, and is manifesting itself as a crash.
Change i <= x to i < x etc, or increase the grid size.

Related

What should I do with unhandled exception

I tried a lot of things to do but it still show me the same, that there is unhandled exception: access violation writing location in VS. But it doesn't happen when i sorting 1d array. What can I try next?
int main(void) {
static int a[3][4]{}, ab[3][4]{};
int i, j, k, N, M;
int* a1=nullptr;
printf("Matrica mora da ima velicinu 3 sa 4\n");
printf("Enter the order \n\n\t");
scanf_s("%d%d",&N ,&M);
for (i = 0;i < M;++i)
{
for (j = 0;j < N;++j)
{
scanf_s(" %d", &a[i][j]);
ab[i][j] = a[i][j];
}
printf("\n");
}
for (i = 0;i < M;++i) {
for (j = 0;j < N;++j) {
printf(" %d", a[i][j]);
}
printf("\n ");
}
//classic sorting
for (i=0; i < M; ++i)
{
for (j = 0;j < N;++j)
{
for (k = j + 1;j < N;++k)
if (a[i][j] > a[i][k])
{
*a1 = a[i][j]; // there is exception thrown
a[i][j] = a[i][k];
a[i][k] = *a1;
}
}
}
First off, there is a problem with static allocation of arrays, but there is no sanitization of N and M after the user inputs them. That means that you allocate only a matrix of 3x4, but the user can input and write to a matrix of any dimensions (e.g. 10x10), which could lead to access violation.
I'd recommend either having sanitation of the input values, e.g.
// It's always better to have limits as constant.
const int MAX_N = 3;
const int MAX_M = 4;
static int a[MAX_N][MAX_M];
...
scanf_s("%d%d",&N ,&M);
// Check if the dimensions can be fitted into the statically allocated array.
if(N > MAX_N || N <= 0 || M > MAX_M || M < 0)
{
// indicate invalid dimensions, either by returning from main with -1
// or calling exit(-1), or throwing an exception.
return -1;
}
In case the input didn't exceed 3x4, another thing that could be problematic - i goes from 0 to M, not N (what I would expect), which could also be problematic. The way matrix addressing works in C/Cpp is that the matrix is linearized into an array, and accessing it with a[i][j] leads to accessing the array with a[i*MAX_J + j]. In your case, the array has 12 elements (3x4), and MAX_J=4, so accessing it with a reverse set of indexes a[4][3] will access a[4*4+3]=a[19], which will access memory from outside of the array.
On the access violation writing problem, a1 isn't allocated, so when you try do execute *a1= ... you are writing to nullptr, which is a protected address, hence the access violation when writing. The way to solve this is either to:
have a1 be a int variable (not a pointer)
first allocate memory for a1 by executing a1 = malloc(sizeof(int)); and then freeing it after use with free(a1) (but since it's only a single element, I'd recommend converting a1 to int instead)
assign the address of the matrix element like a1=&a[i][j], but that would not be valid logically in your case (after that, you write into the location the pointer is pointing to, so the original value will be lost).
The reason why it's not happening for the 1d array is probably because of the inverted dimensions - the matrix would probably be 1x4, but you will be accessing it as 4x1, and you are sorting all the values with j index from 0 to 1, and since there is only one value you would not enter the k loop.

How to store the sum of two integers into a long variable in C?

I created a matrix of ints for example have {1 , 2 , 3 , 4 , 5}
and then I'm trying to store the sum of the matrix into a long variable:
#include<stdio.h>
#define m 5
int main (){
int i;
int matrix[m];
long matrix_sum;
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
for(i = 0; i < m ; i++) //adding ints to long
matrix_sum += matrix[i];
printf("%lo \n",matrix_sum);
return 0;
}
when I run this code I have "17" on output instead of "15" !!
Think about what happens on the first iteration of this loop:
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
Notice that you'll be reading from index -1 of this array (oops!) This leads to undefined behavior, which means that in principle anything can happen. Your program could get garbage data, get the wrong answer, or even outright crash!
It's up to you to decide how to avoid this case. Consider changing the loop indices so that you start at a higher index.
Also, look at the remaining variables in main. Are they initialized? If not, adding values to them will again result in undefined behavior and pretty much anything can happen to them.
Finally, look at how you're printfing things:
printf("%lo \n",matrix_sum);
The %lo specifier means "the argument is a long, and it should be printed in octal (base-8)." This means that you're not printing the value in decimal, so even if you'd expect to get the value 15dec, you'd instead see 17, the octal representation of the number.
I have not seen a matrix. It seems you mean an array or a vector.
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
The variable matrix_sum was not initialized.
In this loop
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
^^^^
there is an attempt to access memory beyond the array when the variable i is equal to 0.
And it looks like you wanted to use the conversion specifier %ld in this statement
printf("%lo \n",matrix_sum);
^^^
Otherwise the output will be as an octal number.
I think you mean the following. At least the program output is exactly equal to 15.:)
#include <stdio.h>
#define N 5
int main(void)
{
int a[N];
int i;
long sum;
for ( i = 0; i < N ; i++ ) a[i] = i + 1;
sum = 0;
for ( i = 0; i < N ; i++ ) sum += a[i];
printf( "%ld\n", sum );
return 0;
}

Why does this code gives segmentation fault with some inputs?

//difference of two diagonals of a N x N matrix
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int N, j, i,k,l;
scanf("%d",&N);
int array[N-1][N-1], sum1=0, sum2=0, sum=0;
for(i=0;i<N; i++)
{
for(j=0; j<N; j++)
{
scanf("%d",&array[i][j]);
}
}
for(k = 0; k<N; k++){
sum1 += array[k][k];
}
for(l=0; l<N; l++){
sum2 += array[N-1-l][l];
}
sum = abs(sum1 - sum2);
printf("%d",sum);
return 0;
}
The above code generates segmentation fault for some inputs. The program calculates absolute difference between the summation of all the values in the two main diagonal.
The main problem, I think, is that you're declaring your array of size N - 1 × N - 1, but then filling in N elements. Do try declaring it N×N.
You declared array array as having N-1 rows and N-1 columns
int array[N-1][N-1], /*...*/;
So the valid range of indices for rows and columns of the array is [0, N-2]
However in the loops of the program you are trying to access elements of the array with indices N-1. For example
for(i=0;i<N; i++)
{
for(j=0; j<N; j++)
{
scanf("%d",&array[i][j]);
}
}
that is you are trying to access memory beyond the array and as result the program has undefined behaviour.
Simply write the declaration of the array like
int array[N][N], /*...*/;
Take into account that the sizes of the array shall be positive values.
Also you may remove headers
#include <string.h>
#include <math.h>
because no declaration from the headers is used in the program.
First of all, invalid input will cause Undefined Behavior.
You need to ensure that the input is valid, for that you can check scanf()'s return value, like this
if (scanf("%d", &N) != 1)
return -1;
Then you need to ensure that N > 0, because you allocate space for N - 1 items, so
if (N <= 1) /* this also prevents `int array[0][0];' */
return -1;
should be added.
Then you have to fix your loops, you allocate space for N - 1 items but you do N iterations from 0 to N - 1, N - 1 is an invalid index if you have only allocated N - 1 elements, you need to do one of two things
Fix the loop
for (int i = 0 ; i < N - 1 ; ++i) /* ... etc. */
Allocate space for N elements,
int array[N][N];
in this case you should change the check on N, to
if (N < 1)
return -1;
The reason why different input triggers different behavior, is because accessing an array beyond it's limits causes undefined behavior. So it will sometimes work some other times it will cause a segmentation fault and even some other times something else because it's undefined.
But there is yet another source of undefined behavrior that also depends on input and it's the way you used scanf(). If you type asdasd then N will be uninitialized when you declare your array variable, hence undefined behavior will happen too.

Can you use double brackets in a nested for loop?

What I mean by my question is that if I have a nested for loop like
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; i++)
{
printf("%d\n"___);
}
}
What would I put in the blank? Would [i][j] be illegal if I declared an array already?
I am not sure what exactly you are stuck on based on your question so I made a minimal C program with comments
I declared an int array who's first and second dimension are at least 10 because you iterate both i and j from 0 to 9 (inclusive). This is to avoid out of bounds problems while iterating
The array's elements are not initialized in the program. It is possible that this program will print all zeros when you run it. It is also possible that it prints other values that happened to be in memory (because the array values are not initialized)
Last I declared i and j outside the for loop just in case this was the problem you were facing
#include <stdio.h>
int main(int argc, char** argv) {
// Declare an array
// Note that both dimensions are at least 10
// Also note that none of the values are initialized here
int myArray[10][10];
// Both i and j are declared here rather than in the for loop
// This is to avoid the following potential error:
// error: 'for' loop initial declarations are only allowed in C99 or C11 mode
int i, j;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
// Note that the values this prints are uninitialized
printf("%d\n", myArray[i][j]);
}
}
return 0;
}
Your question was really unclear. But from what I understand is you have some 2-d array, and you want to print contents of array.
You must have arrary already defined as int arr[10][10], then you can use,
printf("%d\n", arr[i][j]);

How do you break an array in to little arrays of a fixed size? (in C)

I was trying to do an exercise in Hacker Rank but found that my code(which is below) is too linear. To make it better I want to know if it is possible to break an array in to little arrays of a fixed size to complete this exercise.
The Exersise on HackerRank
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int N, M, Y, X;
scanf("%d %d %d %d", &N, &M, &Y, &X);
int max = 0;
int total = 0;
int data[N][M];
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
scanf("%d",&(data[i][j]));
}
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
total = 0;
for(int l = 0; (l < Y) && (i + Y) <= N; l++)
{
for(int k = 0; (k < X) && (j + X <= M); k++)
{
total += data[i+l][j+k];
}
if(total > max)
max = total;
}
}
}
printf("%d",max);
return 0;
}
While "breaking" it into pieces implies that we'd be moving things around in memory, you may be able to "view" the array in such a way that is equivalent.
In a very real sense the name of the array is simply a pointer to the first element. When you dereference an element of the array an array mapping function is used to perform pointer arithmetic so that the correct element can be located. This is necessary because C arrays do not natively have any pointer information within them to identify elements.
The nature of how arrays are stored, however, can be leveraged by you to treat the data as arbitrary arrays of whatever size you'd like. For example, if we had:
int integers[] = {1,2,3,4,5,6,7,8,9,10};
you could view this as a single array:
for(i=0;i!=10;i++){ printf("%d\n", integers[i]); }
But starting with the above array you could also do this:
int *iArray1, *iArray2;
iArray1 = integers;
iArray2 = integers + (5 * sizeof(int));
for(i=0;i!=5;i++){ printf("%d - %d\n", iArray1[i], iArray2[i]);}
In this way we are choosing to view the data as two 5 term arrays.
The problem is not in the linear solution. The main problem is in your algorithm complexity. As it's written it's O(N^4). Also I think your solution is not correct since:
The ceulluar tower can cover a regtangular area of Y rows and X columns.
It does not mean exactly Y rows and X columns IMHO you could find a solution where the are dimension is less than X, Y.
The problems like that are solvable in reasonable time using dynamic programming. Try to optimize your program using dynamic programming to O(N^2).

Resources