I was writing a test code in C and came across something which didn't make complete sense to me. I have an array of integer elements and whenever I try to copy (value of) one of those elements to an integer pointer, I get a segmentation fault. The segmentation fault is coming from the integer pointers because if I use a regular integer (instead of int*), then there is no segmentation fault. I am trying to figure out why am I getting a segmentation fault for storing an integer value like *max = arr[0]
.
Can someone please clarify why it is seg faulting? Since this is not a final code, you may find the comparison arr[0] > arr[1]
little absurd. Please kindly ignore that. My goal is to figure out the reason for segmentation fault.
int main (int argc, char **argv) {
int arr[] = {1000, 11, 445, 1, 330, 3000};
int len = sizeof(arr)/sizeof(arr[0]);
int *min;
int *max;
// Please ignore the reasoning behind this comparison since
// it is simply a test code in progress.
// My goal is to find out why this assignment is seg faulting
if (arr[0] > arr[1]) {
*max = arr[0]; <----Seg fault here.
*min = arr[1];
}else {
*min = arr[0];
*max = arr[1];
}
// Calculate min and max in array and stores those values in `min` and `max`
calculateMinMax (arr, len, min, max);
printf("Min Value:%d", *min);
printf("Max Value:%d", *max);
return 0;
}
Result in GDB
Program received signal SIGSEGV, Segmentation fault.
0x00005555555552bf in main (argc=1, argv=0x7fffffffe208) at minmaxarray.c:32
32 *max = arr[0];
(gdb)
CodePudding user response:
When you work with pointers, you always have to keep in mind the distinction between the pointer itself, versus the value that the pointer points to. And until you've set the pointer itself to point somewhere, the concept "the value that the pointer points to" is meaningless.
For a pointer variable int *max
, when you say
max = ...
you're setting the pointer itself, and when you say
*max = ...
you're setting the value that the pointer points to.
But in the code you've posted, you've got lines like
*max = arr[0];
You're trying to set the value that the pointer points to, before you've set the pointer to point anywhere. As I said, this is meaningless, and it tends to result in a segmentation fault or other such fatal error.
As others have posted, if you want min
and max
to point to the certain elements in the array, you want something like
max = &arr[0];
If you just wanted *max
to be a value fetched from the array, that's what
*max = arr[0];
might do, but first, you'd have to make sure max
pointed somewhere. You could do
int temporary_storage_for_max;
max = &temporary_storage_for_max;
after which lines like
*max = arr[0];
would work. But in that case, it would be silly to use pointers at all. In that case, you might as well declare max
as a plain int:
int max;
and then do things like
max = a[0];
But I'm guessing you do want min
and max
to be pointers, in which case, as mentioned,
max = &arr[0];
is the way to go.
Your calculateMinMax
function probably needs work, too, but since you haven't shown that it's hard to say what it might need. (Conceivably, if calculateMinMax
does the min/max-finding work and does it properly, you don't need these initial assignments of min
and max
at all.)
CodePudding user response:
You want to assign max
to &arr[0]
, not the value of the first item in the array to the address in the pointer, as the pointer's value is currently undefined.
i.e.
max = &arr[0];
min = &arr[1];
etc.
CodePudding user response:
This code snippet
if (arr[0] > arr[1]) {
*max = arr[0]; <----Seg fault here.
*min = arr[1];
}else {
*min = arr[0];
*max = arr[1];
}
does not make a sense. The pointers max
and min
are not initialized. So dereferencing them invokes undefined behavior.
Moreover you have the function calculateMinMax
that has to determine the maximum and minimum elements in the array.
So instead of the above code snippet just write
calculateMinMax (arr, len, &min, &max);
Pay attention to that you need to pass the pointers min
and max
to the function by reference through pointers to them. Otherwise the function will deal with copies of values of the pointers and changing the copies will not change the original pointers.
The function can be declared and defined the following way
void calculateMinMax( const int a[], size_t n, int **min, int **max )
{
*min = ( int * )a;
*max = ( int * )a;
for ( size_t i = 1; i < n; i )
{
if ( **max < a[i] )
{
*max = ( int * )( a i );
}
else if ( a[i] < **min )
{
*min = ( int * )( a i );
}
}
}
Here is a demonstration program.
#include <stdio.h>
void calculateMinMax( const int a[], size_t n, int **min, int **max )
{
*min = ( int * )a;
*max = ( int * )a;
for (size_t i = 1; i < n; i )
{
if (**max < a[i])
{
*max = ( int * )( a i );
}
else if (a[i] < **min)
{
*min = ( int * )( a i );
}
}
}
int main( void )
{
int arr[] = { 1000, 11, 445, 1, 330, 3000 };
size_t len = sizeof( arr ) / sizeof( arr[0] );
int *min;
int *max;
calculateMinMax( arr, len, &min, &max );
printf( "Min Value: %d\n", *min );
printf( "Max Value: %d\n", *max );
}
The program output is
Min Value: 1
Max Value: 3000