Array declaration: C Segmentation fault - c

I am trying to write an array (2x20000) on C. The test code is:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double test( int smod )
{
//
// test subroutine
//
double vect_fma[2][20000];
int i;
// write on file //
FILE *f = fopen("file.txt", "w");
///////////////////
for( i = 1; i < 20001; i = i + 1 ){
// allocate the vector for the fma analysis
vect_fma[1][i] = i*smod;
vect_fma[2][i] = i*smod;
if ( i%smod == 0 )
fprintf(f, "%f %f %f \n", 1.0*i, vect_fma[1][i],vect_fma[2][i] );
}
fclose(f);
return 0;
}
int smod;
void main()
{
smod = 10; // every 10 print the output
test(smod); // call the function
}
I compiled the code with gcc test.c -lm -o test and I received Segmentation fault (core dumped) .
As far as I am new on C, I understand that "the compiler tries to store it on the stack" and a solution could be the one presented in the linked page....but that solution looks quite weird (and complex to understand) if compared with more simple fortran declaration of array real(8), dimension(n:m) :: vect_fma which I can put in a subroutine or in a function without problems.
Is maybe that the declaration I wrote in the code is similar to the fortran real(8), dimension(n,m),allocatable :: vect_fma one ?
So the question is, it exist a simpler way in C to declare an array inside a function ?
Many thanks to everybody.

You have out of bounds access in multiple places, which is undefined behaviour.
In C, an array index ranges from 0 to N-1, not from 1 to N. That means, rewriting the loop part to:
for( i = 0; i < 20000; i = i + 1 ){
// allocate the vector for the fma analysis
vect_fma[0][i] = i*smod;
vect_fma[1][i] = i*smod;
if ( i%smod == 0 )
fprintf(f, "%f %f %f \n", 1.0*i, vect_fma[0][i],vect_fma[1][i] );
}
It's possible 2x20000 doubles might be too big for the stack size on your system, you'd better off fixing the undefined behaviours first
and see if the problem disappears.

The problem is your for loop. You should begin with an iteration where i=0 and end with an iteration where i=19999. Your code begins with an iteration where i=1 and ends with an iteration where i=20000.
The problem is that that there is no 20000th element of your array, only a 19999th (zero indexed). When you access the the 20000th element your accessing system memory that was never allocated for your program which is causing a segmentation fault.
Fix your for loop and you should be good.

Related

Having issues with printing an array in c

I'm having issues on printing an array, that's what I'm doing:
#include <stdio.h>
#define DIM 5
int main () {
double data[DIM] = {128.5, 131.4, 133.2, 127.1, 130.9};
printf("%lf", data[DIM]);
return 0;
}
The answer is always 0.000000.
I've also tried to put the values separately, like this:
#include <stdio.h>
#define DIM 5
int main () {
double data[DIM];
data[0]=128.5;
data[1]=131.4;
data[2]=133.2;
data[3]=127.1;
data[4]=130.9;
printf("%lf", data[DIM]);
return 0;
}
And still the answer is always 0.000000.
Could someone please help. Thank you in advance!
As 4386427 and 500 - Internal Server Error pointed out, there are two issues at work here.
You are trying to print an out-of-bounds index. When you make an array of length 5, indexes go from 0 to 4.
More importantly, there is no specific "print array" function that I am aware of. Your best bet is to create a loop that prints each element of the array.
void printDoubleArray(double arr[], int length)
{
printf("[");
if (length > 0)
{
printf("%f", arr[0]);
}
for (int i = 1; i < length; i++)
{
printf(", %f", arr[i]);
}
printf("]\n");
}
In this call
printf("%lf", data[DIM]);
you are trying to output a non-existent element of the array with the index DIM while the valid range of indices for the array is [0, DIM). This record means that 0 is included in the range as a valid index and DIM is excluded from the range.
As a result the call of printf invokes undefined behavior.
Also you should use the conversion specifier f instead of lf. The length modifier l does not have an effect used with the conversion specifier f. So it is just redundant.
You can not output a whole array except character arrays (by means of the conversion specifier s).
To output the whole array you need to use a loop as for example
for ( size_t i = 0; i < DIM; i++ )
{
printf( "%.1f ", data[i] );
}
putchar( '\n' );
Here is a demonstrative program.
#include <stdio.h>
#define DIM 5
int main(void)
{
double data[DIM] = { 128.5, 131.4, 133.2, 127.1, 130.9 };
for ( size_t i = 0; i < DIM; i++ )
{
printf( "%.1f ", data[i] );
}
putchar( '\n' );
return 0;
}
The program output is
128.5 131.4 133.2 127.1 130.9
C, the language itself, does not have array bounds checking. You want the element one past the end? sure thing. You want the element a million past the end? sure you can ask for that too (who knows what will happen but you can ask for it)
If your compiler supports it, you can get more robust error reporting. Not C standard but helpful nonetheless.
GCC:
Compile with -fsanitize=address and at run-time the sanitizer will catch this overrun:
=======================
==220715==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffed8db4988 at pc 0x559ba54babcc bp 0x7ffed8db4920 sp 0x7ffed8db4910
READ of size 8 at 0x7ffed8db4988 thread T0
#0 0x559ba54babcb in main /tmp/overrun.c:9
clang:
In addition to the run-time sanitizer (-fsanitize=address), Clang can also point out your problem at compile time:
printf("%lf", data[DIM]);
^ ~~~
overrun.c:7:5: note: array 'data' declared here
double data[DIM] = {128.5, 131.4, 133.2, 127.1, 130.9};
^
1 warning generated.

How to use more than one dynamic allocation on C programming?

I'm making a program that reads two sets of data (float) from two different .txt files, and then it transfers these data to two different arrays, which will be used in further calculations. However, when I try to use dynamic allocation more than once, something goes wrong and the data seem not to be stored in the array.
The following simplified program seems to be working fine:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
float *VarA;
int n = 0;
int *counter;
int i;
FILE *input1;
input1 = fopen("C:\\Users\\...test.txt","r");
VarA = (float*)calloc(20001, sizeof(float));
for(i = 0; i < 20001; i++)
{
fscanf(input1,"%f",&VarA[i]);
printf("%f\n",VarA[i]);
}
free(VarA);
fclose(input1);
return 0;
}
it successfully shows the data stored in the array VarA. However, if I introduce a new array to count the number of lines in the file (which is necessary for my further calculations), I just get the value 0.000000 from every array element:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
float *VarA;
int n = 0;
int *counter;
int i;
FILE *input1;
input1 = fopen("C:\\Users\\...test.txt","r");
counter = (int*)calloc(100000, sizeof(int));
while(fscanf(input1,"%f",&counter[n]) != EOF)
{
n++;
}
free(counter);
printf("n = %i\n", n);
VarA = (float*)calloc(n, sizeof(float));
for(i = 0; i < n; i++)
{
fscanf(input1,"%f",&VarA[i]);
printf("%f\n",VarA[i]);
}
free(VarA);
fclose(input1);
return 0;
}
I know that I can avoid using another array to count the number of lines. The point is that every time I use another array, for any purpose, I get the same result. For instance, if I don't use an array to count the number of lines, but I make another one to store my other set of data, one of these arrays just won't present the data after the reading. I tried to modify my program several times in order to find the source of such behavior, but without success.
(At least) two major problems: first,
counter = (int*)calloc(100000, sizeof(int));
while(fscanf(input1,"%f",&counter[n]) != EOF) {
n++;
}
free(counter);
is basically saying "Grab me a chunk of memory, fill it with data as I read the file, then throw it away without ever using it." Probably not what you intended. Then,
VarA = (float*)calloc(n, sizeof(float));
for (i = 0; i < n; i++) {
fscanf(input1,"%f",&VarA[n]);
printf("%f\n",VarA[n]);
}
free(VarA);
which says, "Grab a big chunk of memory, then read data from after the end of the file I just read everything from, put it there, then throw it away."
If you want to read the data from the same file again, you'll have to close it an reopen it (or "seek" to the start). And if you want to do anything with it, you'll have to do it before free()ing the memory you loaded it into.
counter = (int*)calloc(100000, sizeof(int));
// ^--- `int*` ^--- `int`
// v--- `int` pointer
while(fscanf(input1,"%f",&counter[n]) != EOF)
// ^--- `float` designator
Do you see any discrepancies here? Your code allocates ints, then passes a pointer to those ints to fscanf telling it they're floats (using the %f designator). According to the C standard draft n1570, section 7.21.6.2p10 this constitutes undefined behaviour:
If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
My suggestion would be to use the * assignment suppression modifier here, for example:
while (fscanf(input1, "%*f") != EOF) n++;
or, alternatively
while (fscanf(input1, "%f", &(float){0}) != 1) n++;
Note also how I've changed the check from EOF to 1. You can find more information about the return values of fscanf here (which you really should read before using any scanf-related function... and stop guessing, because guessing in C can be harmful).
Additionally, you need to rewind your file once it reaches EOF, otherwise every call to fscanf following this loop will return EOF:
rewind(input1);
P.S. Don't cast malloc in C. This goes for calloc and realloc, too. There's a lot of this quoted stuff that has opengroup manuals of its own; I'll leave it as an exercise to you to find (and read) the opengroup manuals.

Please explain use of scanf() within while loop

I am in the process of learning C thoroughly. I got the code below from another site and have some questions about it. I apologize in advance if I am not using this site correctly. I am new to posting here. Can someone please explain why scanf() is used in the while loop and not before it?
#include <stdio.h>
#include <conio.h>
void main()
{
int a[2][2],*p;
p = &a[0][0];
printf("enter 4 numbers\n");
while ( p < (&a[0][0]+4) && scanf("%d",p++) );
printf("the numbers are\n");
p=&a[0][0];
while( p < (&a[0][0]+4) && printf("%d",*p++) );
}
conio.h was used in MS-DOS. Are you using MS-DOS? Probably not. Don't include this header.
Add a {} or ; to the end of each while loop. This is proper syntax. Otherwise, you will get a parser error.
While this code will print the four values entered once you fix those issues, it is a convoluted way to teach you about loops. printf will return the number of characters printed. scanf on success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.
&a[0][0]+4 are memory addresses. Each time you run this program, you will get different memory addresses.
p=&a[0][0] will start p at the beginning to prepare it to print out the values in the next while loop.
You can read more on pointer arithmetic of multi-dimensional arrays here.
The integer pointer variable p is already initialized. In the while loop this reference is checked to see whether the array holds the four numbers.
while ( p < (&a[0][0]+4) && scanf("%d",p++) );
the actual code is
#include <stdio.h>
#include <conio.h>
int main()
{
int a[2][2],*p;
p = &a[0][0];
printf("enter 4 numbers\n");
while ( p < (&a[0][0]+4) && scanf("%d",p++) );
printf("the numbers are\n");
p=&a[0][0];
while( p < (&a[0][0]+4) && printf("%d",*p++) );
return 0;
}

C code appears to misplace values read with fscanf

I wrote a C program that is behaving in a way I don't understand. I am posting this in the hope that I will learn a bit more about C. The code seems to be writing variable names into other variables using fscanf when that was not asked of it at all...
#include <stdio.h>
#include <stdlib.h>
int main() {
float BCL[6];
float varsRA[23],varsLA[23],varsBB[23],varsPV[23];
FILE *inputfil;
int i;
inputfil = fopen ("file.txt", "rt");
for(i=0;i<24;i++) {
fscanf(inputfil,"%f %f %f %f\n", &(varsRA[i]), &(varsLA[i]), &(varsBB[i]), &(varsPV[i]));
}
i=23;
printf("vars%d:%f %f %f %f\n",i,varsRA[i], varsLA[i], varsBB[i], varsPV[i]);
i=0;
while(!feof(inputfil)) {
fscanf(inputfil,"%f ",&(BCL[i]));
i++;
}
i=23;
printf("vars%d:%f %f %f %f\n",i,varsRA[i], varsLA[i], varsBB[i], varsPV[i]);
fclose(inputfil);
return 0;
}
The outcome is:
vars23:-66.336823 -68.164223 -57.850136 -60.762585
vars23:-66.336823 -68.164223 -57.850136 177.000000
Why was the last value of varsPV changed to 177, which is the first value of BCL, when I read the rest of the file?!
Many thanks for your help,
Marta
The program has undefined behaviour as it is accessing beyond the bounds of the arrays:
for(i=0;i<24;i++) {
fscanf(inputfil,"%f %f %f %f\n", &(varsRA[i]), &(varsLA[i]), &(varsBB[i]), &(varsPV[i]));
}
Array indexes run from 0 to N - 1, where N is the number of elements in the array.
The arrays are defined with 23 elements, meaning valid indexes are from 0 to 22. Change the loop terminating condition to i < 23 or use a compile time constant to define the array size and the terminating condition to avoid duplicating that piece of information.
There are other out of bounds accesses in the program and this loop needs protection from going out of bounds:
i=0;
while(!feof(inputfil)) { /* i < 6 required */
fscanf(inputfil,"%f ",&(BCL[i]));
i++;
}
Always check the return value of fscanf() to ensure assignments were actually made. fscanf() returns the number of assignments made:
for (i = 0; i < 6 && 1 == fscanf(input, "%f", &BCL[i]); i++);
Your arrays aren't being defined big enough. The array varsRA[23] only contains 23 elements numbered 0 through 22. You're reading in 24 elements numbered 0 through 23. Change your array definitions to the following and you should be good to go.
float varsRA[24],varsLA[24],varsBB[24],varsPV[24];
Array indices in C are zero-based.
float varsRA[23],varsLA[23],varsBB[23],varsPV[23]
Those arrays have 22 as their last valid index, which makes 23 elements. That's why
for(i=0;i<24;i++)
writes one extra element to each of them. What you get is undefined behavior (so there is nothing reasonable to expect), but your particual kind of undefined behavior is overwriting a piece of another array (and probably some random memory location).

Segmentation Fault in Function returning Pointer to Array

I am working on a simple softmodem program. The modem is designed to implement the Audio FSK of a dial-up modem and should be able to initiate a phone call by emitting DTMF tones. Currently I am having some problems with a function which will generate sine values.
double* generate_sine( int numberOfElements, double amplitude,
double phase_in_degrees, double numberOfCycles)
{
static int i;
double *sine_output;
sine_output = malloc( numberOfElements*sizeof(double) );
for( i=0; i<numberOfElements; i++ )
{
sine_output[i] = (amplitude*sin(( (2.0*M_PI*i*numberOfCycles)/(double)numberOfElements )+
((M_PI*phase_in_degrees)/180 )));
}
return sine_output;
}
There is a segmentation error in the function. the variable "i" appears to become a pointer after the first iteration of the loop, its value is 4206692. sine_ptr also has a valid address until the second iteration of the loop at which point it become 0 (NULL).
Here is where the function is called. DEFAULT_PHASE = 0.0
int main()
{
int i;
int numElements = 10;
double* sine_ptr = generate_sine( numElements, 0.5, DEFAULT_PHASE, 440 );
for( i=0; i<numElements; i++)
{
printf( "%e \n", *(sine_ptr + i ) );
}
free(sine_ptr);
return 0;
}
After taking all of the edit suggested into consideration I was able to solve the problem in my code, thank you very much for any help that you gave me.
EDIT Added another point.
Issue Number 1
You are allocating enough memory for 5 elements (numberOfElements is 5). You are then trying to print 10 elements from the initial point. The last 5 elements will be accessing unallocated space and can result in undefined behavior. Including segmentation faults.
Issue Number 2
You are not freeing the pointer to the allocated space but a location 10 places later. This will also cause other problems if you solve the segmentation fault.
Issue Number 3
This is one of the minor ones. But sine_ptr is double, and trying to show it as int is undefined. will cause compiler warnings. Even with warnings, the numbers are downcasted. In your case the output will be all zeros. To see correct results, use %lf.
Use the following code.
int main()
{
int i;
int numElements = 5;
double* sine_ptr = generate_sine( numElements, 0.5, DEFAULT_PHASE, 440 );
for( i=0; i<numElements; i++)
{
printf( "%lf \n", *(sine_ptr + i) );
}
free(sine_ptr);
return 0;
}

Resources