Why does this C code segfault? - c

I keep getting a segmentation fault in this code:
#include <stdio.h>
void FillArray(int *array, int);
#define MAX 256
int main()
{
int *array[MAX], size = 100;
FillArray(*array, size);
return 0;
}
void FillArray(int *array, int size)
{
int i, temp;
for (i = 0; i < size; i ++)
{
temp = (rand()%101);
*array = temp;
printf ("array[%d]. %d\n", i, *array);
array += i;
}
printf ("AJGIUEROGUSHFDJGJDFK/n");
}
I put the printf on the last line so that i could tell if it would reach that point, so far it hasn't.
Edit: I added code. I have to use pointer arithmetic instead of array indexes.

Your array in main is declared as an array of int * pointers. This array is not initialized, i.e. all elements contain garbage values.
Layer your FillArray call in main
FillArray(*array, size);
passes the value of *array to FillArray function. *array is the same as array[0] - it is an uninitialized garbage pointer that points nowhere.
Inside FillArray function you are attempting to access (and write) data through that uninitialized garbage pointer. Expectedly, the code crashes.
As is always the case with invalid code, there's no way to fix the error until you explain what you are trying to do.
I can only guess that all you needed is an array of int elements, not int * elements. I.e. your array in main was supposed to be declared as int array[MAX]. And FillArray should have been called as FillArray(array, size). Also, inside the cycle it is supposed to be array += 1 (or just ++array), not your array += i, which does not make any sense.

If wanna fill the array passed to your function, then change
array = &temp;
to
*array = temp;
And also change
array += i;
to
array++;
EDIT: OP edited his question and want to fill an array of integers. You need to chage the declaration of your array
int *array[MAX], size = 100; // Declare an array of pointers
to
int array[MAX], size = 100; // Declates an array of ints

Your loop should just be:
int i, temp;
for (i = 0; i < size; i ++)
{
temp = rand() % 101;
array[i] = temp;
printf ("array[%d] = %d\n", i, array[i]);
}
This will do what you want. There's no need to re-assign array inside the function, although you can. It's easier to just use the indexing operator []. Remember that
a[i]
is the same as
*(a + i)
regardless of the types involved (but generally a is a pointer type and i an unsigned integer) as long as the sum is a pointer of course.
There are errors in main(), too:
The array should just be int array[MAX];.
The call should just be FillArray(array, size);.

probably your want.
#include <stdio.h>
#include <stdlib.h>
void FillArray(int *array, int);
#define MAX 256
int main(){
int array[MAX], size = 100;
FillArray(array, size);
return 0;
}
void FillArray(int *array, int size){
int i;
for (i = 0; i < size; i++){
*array = rand()%101;
printf ("array[%d]. %d\n", i, *array);
++array;
}
}

int *array[MAX] is an array of MAX pointers to int, from which you pass the 1st to the function. There are no ints defined where the latter points to.
To fix this appliy the changes void FillArray(int *array, int size) provided by the other answers and then call it like this:
int main(void)
{
int array[MAX], size = 100;
FillArray(array, size);
return 0;
}

Code is fine except for your perception that *array = &array, which is wrong !!
Below points might help in understating pointers better:
*array = array[0]
array = &array[0]
*(array+i) = array[i]
Made changes to your code and it should work fine:
#include <stdio.h>
void FillArray(int *array, int);
#define MAX 256
int main()
{
int *array, size = 100;
array=(int *)calloc(MAX,sizeof(int));
if(array !=NULL)
{
FillArray(array, size); /* While calling send &array[0] but not array[0] */
}
return 0;
}
void FillArray(int *array, int size)
{
int i, temp;
for (i = 0; i < size; i ++)
{
temp = (rand()%101);
*(array+i) = temp;
printf ("array[%d]. %d\n", i, *(array+i));
/* array += i; <-- not necessary */
}
printf ("AJGIUEROGUSHFDJGJDFK/n");
}

Related

Can somone please explain this to me

For n=3 and a={1,2,3},b={4,5,6} its supposed to calculate 1*4+2*5+3*6.
I don't understand why does it work because p is a pointer and p=produs(a,b,n) means that the address of p becomes the value returned by produs.
#include <stdio.h>
#include <conio.h>
void citire(int *x,int *n)
{
for(int i=1; i<=*n; i++)
scanf("%d",&x[i]);
}
int produs(int *a,int*b,int n)
{
int produs=0;
for(int i=1;i<=n;i++)
produs=a[i]*b[i]+produs;
return produs;
}
int main()
{
int n;
int*p;
scanf("%d",&n);
int *a=(int*)malloc(n*sizeof(int));
int *b=(int*)malloc(n*sizeof(int));
citire(a,&n);
citire(b,&n);
p=produs(a,b,n);
printf("%d",p);
return 0;
}
When you do:
size_t size = 10;
int* x = calloc(size, sizeof(int));
You get an array x with 10 items in it, indexed 0..9, not 1..10. Here calloc is used to make it abundantly clear what's being requested instead of doing multiplication that can be mysterious or obtuse.
As such, to iterate:
for (int i = 0; i < size; ++i) {
x[i] ...
}
You have a number of off-by-one errors in your code due to assuming arrays are 1..N and not 0..(N-1).
Putting it all together and cleaning up your code yields:
#include <stdio.h>
#include <stdlib.h>
void citire(int *x, size_t s)
{
for(int i=0; i < s; i++)
scanf("%d", &x[i]);
}
int produs(int *a, int* b, size_t s)
{
int produs = 0;
for(int i = 0; i < s; i++)
produs = a[i] * b[i] + produs;
return produs;
}
int main()
{
int n;
scanf("%d",&n);
int* a = calloc(n, sizeof(int));
int* b = calloc(n, sizeof(int));
citire(a, n);
citire(b, n);
// produs() returns int, not int*
int p = produs(a,b,n);
printf("%d", p);
return 0;
}
You're using pointers in places where pointers don't belong. In C passing a pointer to a single value means "this is mutable", but you don't change those values, so no pointer is necessary nor advised.
Try and use size_t as the "size of thing" type. That's what's used throughout C and it's an unsigned value as negative indexes or array lengths don't make any sense.

How am i using wrongly the void expression?

I'm newbie in C and wanted to create a function that receives one integer n and one array V, and check if my array contains the values of 1 to n.
This is my actual code:
#include <stdio.h>
void checkArray(int n, int* V);
void checkArray(int n, int* V){
int remain = n;
size_t length = sizeof V / sizeof V[0];
for(int i = 0; i<length;i++){
for(int j = 0; j<length;j++){
if(V[j] == remain){
remain--;
}
}
}
if(remain == 0)
printf("It's Latin");
printf("Not Latin");
}
int main(){
int n;
scanf("%d", &n);
int V[] = {1,2,3,4,5,6,7,8};
printf(checkArray(n, V));
}
I'm getting the error at my printf, where it says invalid use of void expression.
Your checkArray() function returns nothing (which is what void means) and you are trying to print that 'nothing' which is obviously impossible. Your checkArray() function already prints the result so you don't need to print anything in main().
It's seems though that you are missing else before printf("Not Latin") and your length variable is also incorrect. The V parameter of your checkArray() function is just a pointer (like a reference) to array and it doesn't hold any size information, you'll have to pass size separately to your function if you want to be able to traverse the array properly.
In my view, there are two mistakes in your program.
1. You didn't put "else" condition in function definition.
2. you already print something in your functions definitions so no need to use 'printf' in main() function.
you just call that function.
and put "return 0;" in last of the main function.
To put together:
#include <stdio.h>
void checkArray(int n, int* V, size_t length);
void checkArray(int n, int* V, size_t length){
int remain = n;
for(int i = 0; i<length;i++){
for(int j = 0; j<length;j++){
if(V[j] == remain){
remain--;
}
}
}
if(remain == 0){
printf("It's Latin");
else {
printf("Not Latin");
}
}
int main(){
int n;
size_t length;
scanf("%d", &n);
int V[] = {1,2,3,4,5,6,7,8};
length = sizeof(V) / sizeof(V[0]);
checkArray(n, V, length);
return 0;
}

Pointer to Pointer array & Stack Smashing error

I need to allocate an array with a malloc and I have to read some numbers from input. This is my code:
#include <stdio.h>
#include <stdlib.h>
void read(int **array, int *array_size)
{
int *tmp;
int i;
scanf("%d", array_size);
*array=malloc(*array_size*sizeof(int));
tmp=malloc(*array_size*sizeof(int));
for(i=0;i<*array_size;i++)
{
scanf("%d", &tmp[i]);
array[i]=&tmp[i];
}
}
//DO NOT EDIT main()
int main()
{
int *array;
int array_size,i;
read(&array,&array_size);
printf("Print array:\n");
for(i=0;i<array_size;i++)
printf("%d\n", array[i]);
return 0;
}
It kinda works, but after displaying values it shows a stack smashing detected (I compiled it with GCC).
I thought the problem is that *array=malloc(*array_size*sizeof(int)), but I can't figure out how to fix it. Is there another way to allocate this array without editing main()? Thank you.
The problem is that you're indexing the wrong array. You should be writing (*array)[i], not array[i]:
void read(int **array, int *array_size)
{
int *tmp;
int i;
scanf("%d", array_size);
*array=malloc(*array_size*sizeof(int));
tmp=malloc(*array_size*sizeof(int));
for(i=0;i<*array_size;i++)
{
scanf("%d", &tmp[i]);
(*array)[i]=tmp[i];
}
}
Of course all this is very complicated - you don't need to actually have that tmp, nor do you need to malloc it. Instead you could very well do something like
void read(int **array, int *array_size) {
int i, *pos;
scanf("%d", array_size);
*array = pos = malloc(*array_size * sizeof(int));
for (i = 0; i < *array_size; i ++, pos ++) {
scanf("%d", pos);
}
}
That is we have the pointer pos to point to the current position in the array where we want to scanf the next integer. On each loop we increment the position.
Naturally, you'd want to check the return values of these scanfs and malloc; and perhaps read should have a different prototype, such as
int *read(int *array_size);
so it could return the pointer to the array directly, or NULL on error.

C: Printing out the value and memory location of each element of an array using pointers?

I have generated a random array inside the main function, How can I properly print it out using a separate function and inside the function print out the value and memory location of each element of that array using pointers. Here is my code so far:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void printArray(int *pointertoArray, int *Size);
int main (void)
{
srand(time(NULL));
int array[10];
int *pointer = NULL;
for(int i = 0; i < size; i++)
{
array[i] = rand();
*pointer = array[i];
printArray(*pointer,size);
}
}
void printArray(int *pointerToArray, int *size)
{
int i = 0;
do
{
printf("\nValue %d = %p ",i,*pointerToArray);
i++;
}
while(i < size);
}
Here is what I am trying to achieve:
value 1 = 0x7fff0815c0e0
.....
value 10 = 0x7fff0815c0ec
int *size should be int size. You don't pass a pointer, and you don't need a pointer.
Actually, size_t size would be more appropriate.
The call to printArray should be located after the loop. You only want to print the array once.
printArray(*pointer, size); should be printArray(array, size);.
pointerToArray should be named array or pointerToInts.
The value of the element is pointerToArray[i], not i.
The address of the element is pointerToArray+i, not *pointerToArray.
The loop in printArray should be top-tested. (No reason for it to be bottom tested, so play it safe.)
main is declared to return an int, but doesn't.
We get,
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void printArray(int *array, size_t size);
int main() {
srand(time(NULL));
int array[10];
for (int i = 0; i < size; ++i) {
array[i] = rand() % 1000;
}
printArray(array, sizeof(array)/sizeof(array[0]));
return 0;
}
void printArray(int *array, size_t size) {
for (int i = 0; i < size; ++i) {
printf("Value # %p = %d\n", array+i, array[i]);
}
}
Alternative:
void printArray(int *pointerToInt, size_t size) {
for (; size--; ++pointerToInt) {
printf("Value # %p = %d\n", pointerToInt, *pointerToInt);
}
}

Initialization and increment of array of pointers to integers

I have written the following code in C for initializing and increment an array of pointers to int.
#include <stdio.h>
#include <stdlib.h>
int * arr;
void initArray (int *arr, int size) {
arr = malloc(sizeof(int)*size);
for (int i=0; i< size; i++) {
arr[i]= i;
printf("%d ", arr[i]);
}
printf("\n");
}
void incArray(int *arr, int size) {
for (int i=0; i< size; i++) {
arr[i]= i+1;
printf("%d ", arr[i]);
}
printf("\n");
}
void main(){
initArray(arr, 3);
incArray(arr, 3);
}
Unless I use malloc in both functions, the program (when run) gives this error:
Running "/home/ubuntu/workspace/hello-c-world.c"
0 1 2
bash: line 12: 93714 Segmentation fault "$file.o" $args
Process exited with code: 139
Not sure why once the initArray function is called why it needs memory allocation again in increment function. I am assuming it's treating the array for the second function as a separate one whereas I want to increment the values in the first array that initArray function creates.
I'd really appreciate being pointed in the right direction.
You want this:
#include <stdio.h>
#include <stdlib.h>
void initArray (int **arr, int size) {
*arr = malloc(sizeof(int)*size);
for (int i=0; i< size; i++) {
(*arr)[i]= i;
printf("%d ", (*arr)[i]);
}
printf("\n");
}
void incArray(int *arr, int size) {
for (int i=0; i< size; i++) {
arr[i]= i+1;
printf("%d ", arr[i]);
}
printf("\n");
}
void main(){
int *arr;
initArray(&arr, 3); // << this will modify arr
incArray(arr, 3);
}
In your code, you have two variables whose name is arr : one is inside the global scope, and the other one is in initArray function scope. Look at this instruction inside initArray :
arr = malloc(sizeof(int)*size);
As function's local scope is resolved before global's one in C language, it's the arr parameter of the function which is going to store the allocation, not the global arr variable. And as you're returning nothing, this pointer will be destroyed at the end of your function, and you will not have any access to your allocation anymore. And so, the global arr will never be modified and its value will always be NULL or an undefined value.
This is why, inside incArray when you're doing this writing instruction...
arr[i]= i+1;
... you are actually trying to write i + 1 in a NULL or undefined address, which is not an address your processus has the right to write in, causing this segmentation fault.
A simple fix would be to return the pointer in initArray and to store it in your global arr variable, like that:
int * arr;
int* initArray (int size) {
int* arr = malloc(sizeof(int)*size);
// ...
return arr;
}
void incArray(int *arr, int size) {
// ...
}
void main(){
arr = initArray(3);
incArray(arr, 3);
}
The arr in initArray() is hiding the global arr, and modifications made to arr in initArray() are not made to the global arr. Your code then calls incArray() with the (unmodified) global arr — which is still a null pointer. This gives you a seg fault when you try to use it. It also means that you leak the memory when the function returns.
You'll need to work out whether you want the global variable or not — I suggest removing it. Global variables should be avoided when possible.
You will need to change the signature of the initArray() function — there are (at least) two options.
Option 1 — Return pointer to allocated space
You could change initArray() to return a pointer to the allocated space. It would have the signature int *initArray(int size) and you'd call it as:
int *arr = initArray(3);
This yields:
#include <stdio.h>
#include <stdlib.h>
int *initArray(int size)
{
int *arr = malloc(sizeof(int)*size);
if (arr != 0)
{
for (int i = 0; i < size; i++)
{
arr[i] = i;
printf("%d ", arr[i]);
}
printf("\n");
}
return arr;
}
void incArray(int *arr, int size) // Unchanged
{
for (int i = 0; i < size; i++)
{
arr[i] = i+1;
printf("%d ", arr[i]);
}
printf("\n");
}
int main(void)
{
int *arr = initArray(3);
if (arr != 0)
incArray(arr, 3);
return 0;
}
Where I compare to 0, you may prefer to compare to NULL. Note that the code is careful to check that allocations succeed before using the allocated space.
Option 2 — Pass a pointer to a pointer
Alternatively, if you like double pointers, you can pass a pointer to a pointer to the function:
void initArray(int **arr, int size)
{
*arr = malloc(sizeof(int) * size);
if (*arr != 0)
{
for (int i = 0; i < size; i++)
{
(*arr)[i] = i;
printf("%d ", (*arr)[i]);
}
printf("\n");
}
}
// incArray unchanged again
int main(void)
{
int *arr;
initArray(&arr, 3);
if (arr != 0)
incArray(arr, 3);
return 0;
}

Resources