Pointer to Pointer array & Stack Smashing error - c

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.

Related

I wrote a function to sort a string in alphabetical order but getting a segmentation fault

sort and swap functions take pointer as argument, when I try it with 2 or 3 strings it works fine but for more than three its giving a segmentation fault, this is my code please let me know what's going on here and why it's giving this error.
#include <stdio.h>
#include <string.h>
void get(int r, int c, char (*s)[c]);
void print(int r, int c, char (*s)[c]);
void sort(int r, int c, char (*s)[c]);
void swap(int c, char (*s)[c], char (*s1)[c]);
void main()
{
int r;
printf("\n\t enter no. : ");
scanf("%d", &r);
char s[r][31];
get(r,31,s);
sort(r,31,s);
printf("\n\tsorted list");
print(r,31,s);
}
void get(int r, int c, char (*s)[c])
{
int i, j;
for(i = 0; i < r; i++)
{
printf("\n\t");
scanf("%s", *(s+i));
}
}
void print(int r, int c, char (*s)[c])
{
int i, j;
for(i = 0; i < r; i++)
{
printf("\n\t%s", *(s+i));
}
}
void sort(int r, int c, char (*s)[c])
{
int i, j, k;
for(i = 0; i < r; i++)
{
for(j = 0, k = 1; j < r-1; j++, k++)
{
if(strcmp(*(s+j),*(s+k)) > 0)
{
swap(c, (s+j), (s+k));
}
}
}
}
void swap(int c, char (*s)[c], char (*s1)[c])
{
char (*t)[c];
strcpy(*t, *s);
strcpy(*s,*s1);
strcpy(*s1,*t);
}
t is a pointer and as such it needs to be initialized, that is the reason for the segmentation fault, you need to allocate and assign the needed memory though a way better solution would be to simply make it an array:
void swap(int c, char (*s)[c], char (*s1)[c])
{
char t[c];
strcpy(t, *s);
strcpy(*s,*s1);
strcpy(*s1,t);
}
Or
char (*t)[c] = malloc(sizeof *t); // you'll need stdlib.h
With this second option you must free the memory:
free(t);
I would strongly advise the first solution though.
I would also strongly advise the use of a width limiter for the scanf in your get function, otherwise you are at risk of buffer overflow and consequently of undefined behavior.
scanf("%30s", *(s+i));
// discard extra characters in case the input is larger than the destination buffer
while ((c = getchar()) != '\n' && c != EOF){}
Note that main return type should be int.
Live sample

why does my program print garbage values when i try using recursion?

i'm new to programming and i'm learning about recursion, i am doing exercise 4 from this page
https://www.w3resource.com/c-programming-exercises/recursion/index.php, i am trying to print the elements of the array once the value of "i" in the recursive function gets to the value of "n", however once i run the program it prints garbage values i think.my question is why does it do that? why doesn't it print the values of the array?
#include <stdio.h>
#include <stdlib.h>
void printr(int n,int i);
int main (void)
{
printf("NUMBER OF ELEMENTS:\n");
int n;
scanf("%i",&n);
printr(n,0);
}
void printr(int n,int i)
{
int arr[n];
if (i == n)
{
for (int j = 0; j < n; j++)
{
printf("%d",arr[j]);
return;
}
}
printf("element %d :\n",i+1);
int e;
//scan for input
scanf("%d",&e);
//populate array
arr[i]=e;
//do it again
printr(n,i + 1);
}
Then i solved it by passing the array defined in the mein function asan argument in the printr function
it worked but i don't understand why my first attemp didn't?
#include <stdio.h>
#include <stdlib.h>
void printr(int arr[],int n,int i);
int main (void)
{
printf("NUMBER OF ELEMENTS:\n");
int n;
scanf("%i",&n);
int arr[n];
printr(arr,n,0);
}
void printr(int arr[],int n,int i)
{
if (i == n)
{
for (int j = 0; j < n;j++)
{
printf("%d ",arr[j]);
}
printf("\n");
return;
}
printf("element %d :\n",i+1);
int e;
//scan for input
scanf("%d",&e);
//populate array
arr[i] = e;
//do it again
printr(arr,n,i + 1);
}
Thank you!
Because basic C: each invocation of printr has its own arr on the stack, initially uninitialized. And you print it without initializing it first.
When you print out the value, it isn't initialized first. When you create the variable to be printed, its pointing to a place in memory. This memory was probably freed by another program (so its up for grabs). As such, it contains "garbage" data. The way to deal with this is to initialize your values.
In order to avoid stuff like this in the future, get in the habit of setting your pointers to NULL when you don't initialize them so that your programs segfaults when your trying to read an uninitialized value.

scanf from function to array

I am trying to scanf values to an array from another function using pointer to pointer. Here's the code:
int initialize(int **arr, int count);
int main()
{
int count;
int *numbers;
scanf("Enter the amount of numbers to enter: %d", &count);
initialize(&numbers, count);
free(numbers);
return 0;
}
int initialize(int **arr, int count)
{
int i = 0;
*arr = calloc(count, sizeof(int));
while(i < count)
{
printf("Nr. %d: ", i + 1);
scanf("%d", &arr[i]);
i++;
}
return 0;
}
It allocates the memory correctly, however, there seems to be a problem inside scanf function in initialize so it crashes after reading in first 2 numbers. Could you help solve it?
arr is a pointer to pointer to int, so 1st make it a pointer to int (before using it like an array) by doing *arr.
So this
scanf("%d", &arr[i]);
should be
scanf("%d", &(*arr)[i]);
or its shorter equivalent
scanf("%d", *arr + i);
Unrelated, but in C it should be at least
int main(void)
Unrelated^2: Sizes and indexes in C best are defined using size_t (coming with stdlib.h).
So the relevant part of your code would look like this:
int main(void)
{
size_t count;
int *numbers;
scanf("Enter the amount of numbers to enter: %zu", &count);
...
int initialize(int **arr, size_t count)
{
size_t i = 0;
*arr = calloc(count, sizeof(int));
while (i < count)
...
Last not least the code misses error checking for the relevant functions:
scanf()
calloc()
Error checking (along with logging the errors) is debugging for free!

Passing array to function using pointer

I'm trying to print array of pointer using pointer instead of array but I got this error Segmentation fault at runtime:
enter number of element:5
array[0]=1
array[1]=2
array[2]=3
array[3]=4
array[4]=5
Segmentation fault
This is the code:
#include <stdio.h>
#include <stdlib.h>
int *array;
int n;
void input(int *array,int n);
void display(int *array,int n);
int sum(int *array,int n);
int main (void) {
int result;
printf("enter number of element:");scanf("%d",&n);
input(array,n);
display(array,n);
result=sum(array,n);
printf("sum of array=%d",result);
return 0;
}
void input(int *array,int n){
int j;
array=(int *)malloc(n*sizeof(int));
for(j=0;j<n;j++){
printf("array[%d]=",j);scanf("%d",array+j);
}
}
void display(int *array,int n){
int j;
for(j=0;j<n;j++)
printf("%d\t",*(array+j));
printf("\n");
}
int sum(int *array,int n){
int sum=0,j;
for(j=0;j<n;j++)
sum+=*array+j;
return sum;
}
How can I fixed this code? please somebody explain me what's wrong with that code.
Variable array is a local variable in function input.
As such, it is pointless to set it with array = ..., because this assignment takes effect only inside the function. You should typically pass its address (&array) to any function that needs to change it.
In your specific example, you also have a global variable array, so a quick solution to your problem would be to simply call function input without passing variable array as an argument:
void input(int n)
{
...
array = (int*)malloc(n*sizeof(int));
...
}
int main()
{
...
input(n);
...
}
Note that this is a "dirty" workaround, and you should typically strive to avoid the use of global variables.
To add the clean version to barak's answer:
int input(int ** array, const size_t n)
{
int result = 0;
assert(NULL != array);
(*array) = malloc(n * sizeof(**array));
if (NULL == (*array))
{
result = -1;
}
else
{
size_t j;
for(j = 0; j < n; ++j)
{
printf("array[%zu]=", j);
scanf("%d", (*array) + j); /* still missing error checking here . */
}
}
return result;
}
And call it like this:
if (-1 == input(&array, n))
{
perror("input() failed");
exit(EXIT_FAILURE);
}
Try this input():
void input(int **array,int n){
int j;
*array=(int *)malloc(n*sizeof(int));
for(j=0;j<n;j++){
printf("array[%d]=",j);scanf("%d",*array+j);
}
}
Because C use pass-by-value, if you want to change the value of a variable in a function, you need to pass the address of that variable as the argument to that function.
In this case, you want to change the value of array in input() and the type of array is int *, therefore the prototype of input() should be something like void input (int **array, ...).
this should do..make sure you understand what the others have said..
#include <stdio.h>
#include <stdlib.h>
int *array;
int n;
void input(int **array,int n);
void display(int **array,int n);
int sum(int **array,int n);
int main (void) {
int result;
printf("enter number of element:");scanf("%d",&n);
input(&array,n);
display(&array,n);
result = sum(&array,n);
printf("sum of array= %d",result);
return 0;
}
void input(int **array,int n){
int j;
*array= malloc(n*sizeof(int));
for(j=0;j<n;j++){
printf("array[%d]=",j);
scanf("%d",(*array)+j);
}
}
void display(int **array,int n){
int j;
for(j=0;j<n;j++){
printf("%d\t",*((*array)+j)); // you can use array notation aswell
//array[0][j] will work
}
printf("\n");
}
int sum(int **array,int n){
int sum=0,j;
for(j=0;j<n;j++){
sum += *((*array)+j);
}
return sum;
}
What does *array + j do? Does it evaluate *array and add j to it? Or does it add j to array and then dereference it? Would you be willing to bet $100 on it if I told you you are wrong?
Make your life and the life of anybody reading your code easier by using parentheses, or even better, write array [j].

Why does this C code segfault?

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");
}

Resources