Segmentation Fault after printing an array? - arrays

I am writing a code to take input from the user, and print it out exactly as it was input, through arrays.
void getArrays(char a[10][10], int b[10], int n ){
printf("Enter number of students and then those students names and scores separated by a space.\n");
scanf("%d", &n);
int i = 0;
while(i < n){
scanf("%s%d", a[i],&b[i]);
i++;
}
}
void printArrays(char a[10][10], int b[10], int n ){
int j;
for(j=0; j<n-1; j++){
printf("%s %d\n", a[j],b[j] );
}
}
In this scenario a is a character array that is 10 rows by 10 columns, while b is an array of ints, sized 10 rows as well. n is a number entered by the user before the arrays are created, specifying the amount of strings to be in the arrays.
The input would look something like this:
5
Jimmy 90
Tony 80
Troy 67
Dona 78
Dylan 97
At this point it cuts off, and prints the arrays, which worked properly. However, after the names were done printing, the terminal spit a multitude of numbers and random strings before giving me this error:
Segmentation Fault (core dumped)
I ran it through the gbd debugger, and was given the following message:
Program received signal SIGSEGV, Segmentation fault.
__strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:65
65 ../sysdeps/x86_64/multiarch/strlen-avx2.S: No such file or directory.
I've searched this error on the site, but the questions already asked didn't relate to my issue;
Weird Segmentation Fault after printing
Segmentation fault core dump
These are just two of the ones I've seen, and they were not the answer I was looking for.
I saw from further searches that it could be a pointer error, or a size discrepancy in the code when referring to an array. I narrowed the problem down to only occurring after it finished printing out the names. So I tried to change for(j=0; j<n; j++) to for(j=0; j<n-1; j++), and once again it gave me the same issues.
I think perhaps the for loop is reading past the number of elements I want it to, ie- instead of stopping at 3, (if n = 3), and it has nothing else to print so it gives me the segmentation fault error?
Do I need to use a pointer with n in this case, such as &n, or is the issue going to be with the size of my array?
The code that calls these functions is as follows:
int main(){
char names[10][15]; // can handle up to 10 students
int scores[10];
int num;
int average;
getScores(names, scores, num);
printScores(names, scores, num);
}

You need to write:
int num;
getScores(... &num);
printScores(... num);
And:
getScores(... int* n)
{
scanf("%d", n)
...
while (i < *n) { // Dereference the pointer `n` to get the value again.
With getScores(... int n) you just pass the current value of num and getScores() only modifies it's local copy of num (which is n); num itself it not changed.
Instead you must pass the "address of" (or "pointer to") num by using int* n.
The garbage you get is because num in main(), which you don't update at all, contains some undefined value (that could come from the processor stack, depending on the implementation of your platform and C compiler).
In your case this garbage/undefined value of num is coincidently higher than 4. This causes your scanned values to be printed plus a lot of again undefined values that are further up in names[] and scores[].
In C it's common to prefix pointers with p, so you may want to write pN instead above.
The above is to get things working. But there's more to say: Currently your arrays have a fixed size. If you'd enter 20 for n and/or enter very long names, your program will behave in undefined ways because your arrays are too small. If you want to stick to fixed sized arrays, you should at least check the value of num and the length of the entered names.

Take into account that the function getArrays is modifying variable n locally (since the function definition is like this:
void getArrays(char a[10][10], int b[10], int n )
and shoudl be like this:
void getArrays(char a[10][10], int b[10], int* n )
So possibly the value of n you are providing to printArrays is not initialized.
On the other hand,in printArrays the loop looks to be wrong defined:
for(j=0; j<n-1; j++)
should be
for(j=0; j<n; j++)

Related

Why does c print a different array the second time it's printed?

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.

C - Does a variable declared in loop get the memory at same place each time the loop executes?

Please read the code below.
#include <stdio.h>
int main(void)
{
char* a[4];
int i=0;
while(i<3)
{
char b[50];
scanf(" %s",b);//Assume user enters one two three
a[i++]=b;
}
i=0;
while(i<3)
printf(" %s ",a[i++]);//Why does it always print three three three
return 0;
}
Clarify the following:
Is it that b gets allocated same 50 bytes in memory each time so that all the elements of array a point to same 50 bytes and thus we get only three printed three times(i.e. what's entered last)
Since after the completion of while, array b can be removed very well but no it remains there every single time printing only three's. Why?
Is it not at all a coincidence that this code prints only three's when it could print one two three, one three three as well. What's wrong?
I know the question is very wrongly put. Forgive me for that. I am new here.
QUESTION #1:
The variable b is a variable that is strictly local to the
while loop.
Therefore, do not reference via a pointer any memory formerly used by b outside (after) the while loop.
Storage for b will be reallocated 3 times.
At the end of the while loop, b will go out of scope.
QUESTION #2:
After the while loop, a is not a valid pointer anymore
because a was assigned to point to b,
and b has gone out of scope after the while loop.
NEVERTHELESS, the memory allocated to b may still
not have been modified. You cannot predict what the value of dereferencing a will be after the while loop - since a is only assigned based on b.
QUESTION #3:
(Please see #2) The code that is dereferencing a after the while loop is using a stale pointer - I would not rely on the output.
The code in the question exhibits undefined behaviour because the second loop attempts to access the data that was only valid in the first loop. Therefore, there is very little that can usefully be said.
The question title is "does a variable declared in a loop get the same address each time the loop executes". Here's a proof by counter-example that the address of the variables in a loop need not always be the same, even in a single invocation of a non-recursive function.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand(time(0));
for (int i = 0; i < 3; i++)
{
int n = rand() % 30 + 5;
char a[n];
for (int j = 0; j < n - 1; j++)
a[j] = rand() % 26 + 'a';
a[n-1] = '\0';
printf("a: %p %2d [%s]\n", (void *)a, n, a);
char b[50+n];
scanf("%s", b);
printf("b: %p %2d [%s]\n", (void *)b, n+50, b);
}
return 0;
}
On a Mac running macOS Sierra 10.12.4 (using GCC 7.1.0), one run of the program (lv83) produced:
$ ./lv83 <<< 'androgynous hermaphrodite pink-floyds-greatest-hits-dark-side-of-the-moon'
a: 0x7fff507e53b0 23 [sngrhgjganmgxvwahshvzt]
b: 0x7fff507e5360 73 [androgynous]
a: 0x7fff507e53c0 9 [wblbvifc]
b: 0x7fff507e5380 59 [hermaphrodite]
a: 0x7fff507e53b0 26 [pqsbfnnuxuldaactiwvjzvifb]
b: 0x7fff507e5360 76 [pink-floyds-greatest-hits-dark-side-of-the-moon]
$
The address at which the two arrays are allocated varies depending on how big they are. By using different formulae for the sizes of the two arrays, the base addresses could be tweaked. It looks as though the compiler rounds the base address of the arrays to a multiple of 16.

printing values of dynamic array

I have made a dynamic array of integers in C, here is my code
#include <stdio.h>
int main(){
int count=0, i, input;
int *myarr;
myarr=(int*)malloc(4*sizeof(int));
while(1){
scanf("%d", &input);
myarr[count]=input;
count++;
if (input == -1) break;
}
for (i=0; i<count; i++){
printf("%d ", myarr[i]);
}
return 0;
}
From the code, I thought i clearly made an array of 4 integers only i.e myarr[0] up to myarr[3], how come when i insert even 10 integers, it still prints all of them, it doesn't print garbage as i thought it would after the fourth integer... Maybe i didn't understand the point of dynamic creating an array?? Make me straight please!
You should only access myarr[0] up to and including myarr[3].
Accessing any other index is undefined behaviour: it might work, it might not.
Also, myarr[count]==input looks like a typo. Did you mean myarr[count] = input? The way you have it is testing if myarr[count] equals input. Technically the way you have it is undefined behaviour for any element of myarr since you are making use of uninitialised data.

Why does the program crash when the function is called in c?

I recently had to create a program where the user enters a certain integer N. After that, my int main() had to call a seperate function, int getNextFibonacciNumber(void), which calculates the Nth term in the fibonacci sequence and then prints it. When I compile the code, Vode::Blocks says that there aren't any errors or warnings. This said, when I try to run the program, it automatically crashes. I have read it and re-read it but I am not able to see where it all went wrong. Would anyone be able to shed some light on this mysery? Thank you very much! When the program crashes, it says: filename.exe has stopped working. A problem caused the program to stop working correctly. Windows will close the program and notify you if a solutions is available. However, when the code is compiled in Code::Blocks, everything is fine.
#include <stdio.h>
#include <stdlib.h>
int getNextFibonacciNumber(void);
int main()
{
int N, fibonacci[N];
printf("Enter a positive integer:");
scanf("%d", &N);
printf("The %d th term in the Fibonacci sequence is: %d", N, getNextFibonacciNumber());
}
int getNextFibonacciNumber()
{
int N, i, fibonacci[N];
fibonacci[0] = 0;
fibonacci[1] = 1;
for(i = 2; i < N+1; i++)
{
fibonacci[i] = fibonacci[i-1] + fibonacci[i-2];
}
return(fibonacci[N-1]);
}
The problem is, that this
int main()
{
int N, fibonacci[N];
invokes undefined behavior. N is not initialized, but used as a C99 variable length array size specifier. Reading a value from a uninitialized variable invokes UB.
To fix this issue you have to write
int main()
{
int N;
printf("Enter a positive integer:");
scanf("%d", &N);
int fibonacci[N];
However there's another problem, namely that you have the same UB causing construct in getNextFibonacciNumber. You have to fix that to. Also the number entered into N is not "communicated" to getNextFibonacciNumber, so I highly doubt that this program worked at all, even if it didn't crash.
Code::Blocks (or rather the compiler Code::Blocks calls) only checks if you have written "legal" c code. It does not (and can not) check if your program does what you want, if your program will exit at any point (or simply run forever), if your program causes errors and crashs and stuff like this.
When you say
int N, fibonacci[N];
I guess you want to create an integer N and an array of the same size. However right now you create an integer N (that has some "random" value, presumably 0) and an array of the FIXED size N.
If you change N late on in your program this does not affect the size of your array "fibonacci" in any way. So if your N was by chance 0 at the beginning of your program than you have created an array of size 0. Even if you read a value (say 5) from the console input. Trying to read and write to this array causes problems.
Moving the part
int fibonacci[N];
below your "scanf" line will fix this problem. At this point N is initialized (and not some random number).
Also be aware that the variable N in the main function
int main()
has no connection at all to the N variable in your function
int getNextFibonacciNumber()
The second N is a newly created variable (again set to some "random" value). If you want to pass data from one function to another you should do it by passing it as an argument in brackets:
int getNextFibonacciNumber( int N)

Input in a 2-D array

I was trying to solve a question on 2-D matrix, but unfortunately the matrix input was giving an error. This is the code:
int arr[4][4];
int r, c;
scanf("%d", &r);
scanf("%d", &c);
int i, j;
fflush(stdin);
for(i = 0; i < r; i++)
for(j = 0; j < c; j++)
scanf("%d", &arr[i][j]);
When I run this, it takes extra input.
For example: if r = 2 and c = 2> then it takes 6 input and then hangs. What to do?
If r=2 and c=2, it executes the first 2 scanf and then the 2x2 scanf of your 2D loop.
This makes 2 + 2x2 = 6.
After the last scanf, if your program is finished, it simply closes, that's normal.
I have copied your code and tried executing it and I observed that it is showing the behaviour told by you if we are taking r and c greater than their limits. So use proper limits.
I think the problem with your code is that you've allocated a fixed amount of space for your array but allowed the user to provide an arbitrary number of inputs by making the bounds of your loop the user-provided r and cvariables. Thus if the user provides r=6 and c=6, at some point your loop will attempt to dereference arr[5][5], which is invalid since you've defined int arr[4][4];. If you want to allow the user to create as many rows and columns as they want, you should initialize arr with the user-provided input, like this:
int r,c;
scanf("%d",&r);
scanf("%d",&c);
int arr[r][c];
In your code you have simply run a loop and how much value will be scan depend on the how many loops has executed.
Suppose you take r=1,c=1.
In this condition for every "r" value c will executed single time.
So When your value will be larger than the array size that time it will give you abnormal behavior.
if you will firstly input the value of "c", and "r"after that it will behave normally.
int r, c;
scanf("%d", &r);
scanf("%d", &c);
int arr[r][c];

Resources