1

What is the problem with the following code? C compiler shows me error: Segmentation fault.

#include <stdio.h> 
#include <math.h>

int main() {
    int n = 4;
    float A[n][n][n][n];
    A[n][n][1][1] = 1;
    A[n][n][1][2] = 0;
    A[n][n][1][3] = -3;
    A[n][n][1][4] = 0;
    A[n][n][2][1] = 1;
    A[n][n][2][2] = 0;
    A[n][n][2][3] = -3;
    A[n][n][2][4] = 0;
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • My guess is that it is execution of your program which triggers the segmentation fault. On my desktop [GCC](https://gcc.gnu.org/) does not crash – Basile Starynkevitch Jun 11 '22 at 11:26
  • @BasileStarynkevitch: *On my desktop GCC does not crash* probably because the optimizer removed everything since the local array is not used: https://godbolt.org/z/4qE7sK1cb – chqrlie Jun 11 '22 at 11:33
  • No: the compiler GCC does not crash. The *compiled executable* does crash. My experience is that GCC is crashing rarely (and I did contribute to it). It is difficult to have a `core` dumped by GCC – Basile Starynkevitch Jun 11 '22 at 11:34
  • @BasileStarynkevitch: of course the execution of the program does... The OP has not yet learned the difference between compilation and execution, which does not exist for interpretive environments. – chqrlie Jun 11 '22 at 11:36
  • @chqrlie: you could play with my [manydl.c](https://github.com/bstarynk/misc-basile/blob/master/manydl.c) program. It generates millions of C lines, and they do not crash and I was unable to crash [GCC](https://gcc.gnu.org/) except by generating pathological code (a single C function of a million lines). Email me to `basile@starynkevitch.net` for more – Basile Starynkevitch Jun 11 '22 at 11:44
  • @BasileStarynkevitch: interesting code to test my own toy compilers. I shall add a warning about the classic [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) for which you have an example in line 459... – chqrlie Jun 11 '22 at 11:56
  • @chqrlie: a more interesting code is of course [Pitrat's CAIA system](https://github.com/bstarynk/caia-pitrat). See also this [AFIA seminar](https://afia.asso.fr/journee-hommage-j-pitrat/) – Basile Starynkevitch Jun 11 '22 at 12:08
  • @chqrlie: and if interested by compilers see also [CompCert](https://compcert.org/) – Basile Starynkevitch Jun 11 '22 at 12:17
  • @BasileStarynkevitch: amazing work! and I am ashamed I was unaware of this 15 year old initiative from prominent French scientists at Inria and Orsay. I would have been proud to contribute had I not left academic research there 37 years ago :) – chqrlie Jun 11 '22 at 12:37
  • I happened to have met many times Jacques Pitrat. I miss him. And Xavier Leroy is at Collège de France.... (Pitrat was the director of my PhD jury) – Basile Starynkevitch Jun 11 '22 at 12:38
  • You could be interested by the [books written by Jacques Pitrat](https://fr.wikipedia.org/wiki/Jacques_Pitrat). – Basile Starynkevitch Jun 11 '22 at 12:43
  • @BasileStarynkevitch: Too bad the Standard doesn't specify any means via which code can indicate that it is intended for a CompCertC compatible compiler, and that implementations must either process it correctly according to such semantics or reject it entirely, *with all other possible behaviors rendering an implementation non-conforming*. – supercat Jun 13 '22 at 23:21

3 Answers3

4

All these assignments access memory outside the defined variable length array.

A[n][n][1][1]=1;
A[n][n][1][2]=0;
A[n][n][1][3]=-3;
A[n][n][1][4]=0;
A[n][n][2][1]=1;
A[n][n][2][2]=0;
A[n][n][2][3]=-3;
A[n][n][2][4]=0;

That is the valid range of indices for each dimension of the array is [0, n ). Thus the expression A[n] is invalid.

It seems you mean the following assignments

A[0][0][0][0]=1;
A[0][0][0][1]=0;
A[0][0][0][2]=-3;
A[0][0][0][3]=0;
A[0][0][1][0]=1;
A[0][0][1][1]=0;
A[0][0][1][2]=-3;
A[0][0][1][3]=0;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    While the answer is correct I think it could be improved in two ways: (1) Mention the technical term "zero-based" array (or perhaps array indexing); and (2) I'm afraid that some readers may not notice the subtlety of "[0,n)" -- it would be clearer if "n-1" appeared somewhere in the answer. – Peter - Reinstate Monica Jun 11 '22 at 11:24
3

If you define an array of length N, the access to the last element is at the N-1 index, and the access to the first element is at index 0 because indexes start from 0 and end at N-1.

So your code should be like this:

#include<stdio.h> 
#include<math.h>
#define N 4

int main() {
    float A[N][N][N][N];
    A[N-1][N-1][0][0]=1;
    A[N-1][N-1][0][1]=0;
    A[N-1][N-1][0][2]=-3;
    A[N-1][N-1][0][3]=0;
    A[N-1][N-1][1][0]=1;
    A[N-1][N-1][1][1]=0;
    A[N-1][N-1][1][2]=-3;
    A[N-1][N-1][1][3]=0;
    return 0;
}

Also, you're using a variable to define the length of your array, which is good only in the C99 standard and onwards. If you don't need a VLA (variable length array), you should use the #define instead.

Freus
  • 181
  • 1
  • 9
0
int n=4;
float A[n][n][n][n];
A[n][n][1][1]=1;

is not valid in every C standard (read n1570 or better). You may want to code const int n=4; or #define n 4

(on cheap microcontrollers you might not even have enough stack space for 256 floats -> possible stack overflow)

And then, you always have a buffer overflow (read about undefined behavior). In A[x][x][1][1] the valid indexes are from x being 0 to x being 3 -that is n-1 - (not 4).

You might want to code

A[n-1][n-1][1][1] = 1;

but you should know that A[0][0][0][0] is being uninitialized. It may contain garbage (signalling NaN), and an hypothetical printf("%f\n", A[0][0][0][0]); could fail ....

I guess that Frama-C would have caught your mistake (I leave you to check that). Be aware of Rice's theorem.

I would initialize A with zeros (to ease debugging, and to have more reproducible runs) -after having corrected the buffer overflow-:

float A[n][n][n][n]={0.0};
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547