Why this code giving me a segmentation fault? - c

#include <stdio.h>
int main()
{
int i,a;
int* p;
p=&a;
for(i=0;i<=10;i++)
{
*(p+i)=i;
printf("%d\n",*(p+i));
}
return 0;
}
I tried to assign numbers from 0 to 10 in a sequence memory location without using an array.

You are trying to write to memory that it does not have permission to access.
The variable a is a local variable in the main function, and it is stored on the stack. The pointer p is initialized to point to the address of a. The code then attempts to write to the memory addresses starting at p and going up to p+10. However, these memory addresses are not part of the memory that has been allocated for the program to use, and so the program receives a segmentation fault when it tries to write to them.
To fix this issue, you can either change the loop condition to a smaller value, or you can allocate memory dynamically using malloc or calloc, and assign the pointer to the returned address. This will allow you to write to the allocated memory without causing a segmentation fault.
Like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
int* p = malloc(sizeof(int) * 11); // Allocate memory for 10 integers
if (p == NULL) { // Check for allocation failure
printf("Error allocating memory\n");
return 1;
}
for(i=0;i<=10;i++)
{
*(p+i)=i;
printf("%d\n",*(p+i));
}
free(p); // Free the allocated memory when you are done with it
return 0;
}

a is only an integer. not an array.
you need to declare it differently:
int i, a[10];

You can not. Memory of int is 4 bytes and you can store only single number in that memory.
for int: -2,147,483,647 to 2,147,483,647
for unsigned int: 0 to 4, 294, 967 295
There are other types you can use with different sizes, but if you want to put different numbers into one variable you need to use array.
int arr[10];
arr[0] = 0;
arr[1] = 5;
something like this.

Related

malloc and pointer questions

We were shown this program in class yesterday and i have a question regarding it's output.
malloc.c:
#include <stdlib.h>
int *create_array(int);
int *create_array(int elements) {
int i,*x = (int *) malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
free(x);
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
return 0;
}
Question(s):
When i run the program, i get this as output:
1627793032
1627793104
2
3
4
However, shouldn't the first 2 elements be 0 and 1 respectively? The values printed here seem like memory addresses to me, am i right? Also, is this due to some mistake causing undefined behavior?
After free(x);, the values pointed to by x are no longer valid. The memory can be reused for some other purpose, and meanwhile the memory allocation library can use the storage as it sees fit.
So, yes, it is a mistake resulting in undefined behaviour.
The real question is why do you even expect it to work? You free x, then you return a freed pointer which is nonsense.
What is happening is the following:
Inside the function you allocate 5 spaces, x points to the first
one's address.
You write 0, 1, 2, 3, 4 in these spaces.
You free x, so all the 5 spaces are not reserved anymore.
You exit the function, doing so the 2 next free memory spaces are
used, which happen to be the ones where you wrote 0 and 1.
You print the values contained in the 5 memory areas you've already
freed, where the ones in which you wrote 0 and 1 happen to have been
reused for something else; hence the weird numbers.
As a general rule, do not attempt to read areas of memory i've freed; even worse, do not try to WRITE there.
Accessing unallocated memory leads to undefined behaviour.
Also, you don't need to declare the function in a separate row if it's going to have nothing in between; plus you don't have to cast what's returned by malloc to the type; it's a void* that by default can hold anything you throw at it. What matters is your base variable type. See here
Corrected code:
#include <stdlib.h>
int *create_array(int elements) {
int i,*x = malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
free(arr);
return 0;
}

accessing variable length array after its memory should have been deallocated

I'm currently studying variable length array and automatic storage.
I have the following code that allocate memory for an variable length array myArray inside function vla, and return a pointer to the variable length array from the function.
#include <stdio.h>
int * vla(int n){
int myArray[n];
myArray[0] = 10;
myArray[1] = 11;
int * pointerToInt = myArray;
return pointerToInt;
}
int main(void){
int * pointerToInt = vla(10);
printf("%d, %d", pointerToInt[0], pointerToInt[1]); // prints 10, 11
return 0;
}
I thought that variable length array belong to the automatic storage class (i.e. the memory for the variable length array will be allocated when we enter the function containing the variable length array, and the memory is automatically deallocated after the function exit)
So according to this logic, the memory allocated to myArray variable length array is deallocated after we return from vla method, but how come I can still correctly access the first and second element of the variable length array?
Is this behavior defined? or it is undefined behaviour that just happen to work?
myArray is a stack/auto variable created on the stack memory. Remember memory always exists. It is just owned by different pointers based on allocation and deallocation. The reason why you can still access same values is that the same piece of memory has not been assigned to another pointer and not been overwritten.
To evaluate it. Create another function that allocates same amount from stack but puts different values. Or add arguments in the same function and call it twice with different values. You will then see the difference.
#include <stdio.h>
int * vla(int n, int a, int b){
int myArray[n];
myArray[0] = a;
myArray[1] = b;
int * pointerToInt = myArray;
return pointerToInt;
}
int main(void){
int * pointerToInt = vla(10, 10, 11);
vla(10, 20, 21); // over write stack
printf("%d, %d", pointerToInt[0], pointerToInt[1]); // prints 20, 21
return 0;
}
By the way returning stack memory from vla is not a good idea. Dynamic memory is allocated from heap using malloc family of functions.
You can still correctly access the first and second element of the variable length array because you are assigning base address of the myArray to pointerToInt. Auto variables have a life inside the block only, but in this program we are using pointer to access the data in the memory, as long as that part of stack is not allocated to any other program, we can access that part of stack. If that part of stack is allocated to some other process we will get segmentation fault as we are trying to access unauthorized memory

Returning an array from a function in C: Segmentation Fault [duplicate]

This question already has answers here:
How is the array stored in memory?
(4 answers)
How to access a local variable from a different function using pointers?
(10 answers)
Closed 6 years ago.
I am trying to implement a simple program using a header file where a function in the header file accepts an int array and returns an int array too.
In header.h:
int* point(int a[]);
In header.c:
#include<stdio.h>
#include "header.h"
int* point(int a[])
{
printf("In the point function\n");
int array[4],i;
for(int i=0;i<4;i++)
{
printf("%dth Iteration\n",i);
array[i]=a[i];
}
return array;
}
In test.c:
#include<stdio.h>
#include "header.h"
void main()
{
int *array,i;
int a[]={1,2,3,4};
printf("calling point function\n");
array=point(a);
printf("Back in the main function\n");
for(i=0;i<4;i++)
{
//SEGMENTATION FAULT HERE
printf("%d\n",array[i]);
}
}
I am getting a segmentation fault at the print loop in test.c.
You cannot return arrays from functions. When point() returns, the local array within this function goes out of scope. This array is created on the stack, and will get destroyed once the function finishes returning. All memory associated with it is discarded, and the returned pointer points to a position on the stack that doesn't exist anymore. You need to instead allocate a pointer on the heap, and return that instead. This allows array to be shared across your program.
Instead of:
int array[4];
you need to dynamically allocate a pointer using malloc():
int *array = malloc(4 * sizeof(*array)); /* or sizeof(int) */
if (array == NULL) {
/* handle exit */
}
malloc() allocates requested memory on the heap, and returns a void* pointer to it.
Note: malloc() can return NULL when unsuccessful, so it needs to be checked always. You also need to free() any memory previously allocated by malloc(). You also don't need to cast return of malloc().
Another thing to point out is using the magic number 4 all over your program. This should really be calculated using sizeof(a)/sizeof(a[0]).
You can declare this as a size_t variable in your main():
size_t n = sizeof(a)/sizeof(a[0]);
Or you can use a macro:
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
And simply call ARRAYSIZE(a) everytime you want the size of the array.
The issue has to do with the scope of the array variable that you're returning in your method. Right now you're returning array, a local variable defined in the method, point. However, once point is finished executing, all local variables within the function frame, including array will be discarded from main memory. So even though you still get a memory address from point, there's no telling what could be at that memory address. Therefore, treating array as an int array when printing out its elements will lead to a segmentation fault.
My suggestion to fix this is to allocate memory from the heap using malloc so that array lasts outside the frame of point. The solution should look like this,
int* point(int a[])
{
printf("In the point function\n");
int *array = (int *) malloc(4 * sizeof(int)); //dynamically allocate memory for 4 integers
int i;
for(i=0;i<4;i++)
{
printf("%dth Iteration\n",i);
array[i]=a[i];
}
return array;
}
You could either define array[] as a global variable, or dynamically allocate memory for it as mentioned in the above comments using malloc().
Since array[] is allocated in the function point(), it gets deleted once the function exits. Hence, a reference to the returned pointer causes a segmentation fault.

Knowing the size of the array using pointer

How can i know the size of the array using a pointer that is allocated using malloc?
#include <stdio.h>
int main(){
int *ptr = (int *)malloc(sizeof(int * 10));
printf("Size:%d",sizeof(ptr));
free(ptr_one);
return 0;
}
I get only the size of the pointer in this case which is 8.How to modify the code to get the size of array which will be 40.
You cannot.
You will need to do the bookkeeping and keep track of it yourself. With new you allocate dynamic memory and while deallocating the memory you just call delete, which knows how much memory it has deallocate because the language takes care of it internally so that users do not need to bother about the bookkeeping. If you still need it explicitly then you need to track it through separate variable.
if your machine is 32 bit you will get pointer size always 4 bytes of any data type
if your machine is 64 bit you will get pointer size always 8 bytes of any data type
if you declare static array you will get size by using sizeof
int a[10];
printf("Size:%lu",sizeof(a));
But you did not get the size of array which is blocked by pointer. where the memory to the block is allocated dynamically using malloc .
see this below code:
#include <stdio.h>
#include<stdlib.h>
int main()
{
int i;
int *ptr = (int *)malloc(sizeof(int) * 10);
// printf("Size:%lu",sizeof(ptr));
// In the above case sizeof operater returns size of pointer only.
for(i=1;ptr && i<13 ;i++,ptr++)
{
printf("Size:%d %p\n",((int)sizeof(i))*i,ptr);
}
return 0;
}
output:
Size:4 0x8ec010
Size:8 0x8ec014
Size:12 0x8ec018
Size:16 0x8ec01c
Size:20 0x8ec020
Size:24 0x8ec024
Size:28 0x8ec028
Size:32 0x8ec02c
Size:36 0x8ec030
Size:40 0x8ec034 //after this there is no indication that block ends.
Size:44 0x8ec038
Size:48 0x8ec03c

integer pointer is not working while assigning two dimensional array via another pointer?

I was trying to copy the contents of one 2d array to another using pointers. I wrote this simple test program but it shows me segmentation fault but i still cannot find a rock solid reason why?
#include <stdio.h>
void main(){
int m[2][3]={
{2,3,4},{5,6,7}
};
int *p=m;
int *n;
int i,j;
for(i=0;i<2;i++){
for(j=0;j<3;j++){
printf("%d \t", *(p+3*i+j));
printf("Debug here\n");
*(n+3*i+j)=*(p+3*i+j);
}
printf("\n");
}
}
// Output:
// 2 Debug here
// Segmentation fault (core dumped)
int *n is an unitialized pointer, you never allocated memory for it, therefore you are trying to write your copy onto unknown territory.
You can alloc space to n using this:
int *n = (int *)malloc(2 * 3 * sizeof(int));
You are not allocating space for your target array. At minimum, you should do:
int *n = malloc(2 * 3 * sizeof(int));
or
int n[2][3];
A pointer is a variable that points to a memory location. It stores the address of the memory location. You can access that location by dereferencing the pointer using *.
In your case,
int *n;
This only declares a pointer to an int. This can point to a single integer or an array integers. You have not yet assigned any value to it (It is still not assigned a memory location). We don't know where it is pointing right now (You might not be allowed to access the memory etc.). (That's why the seg fault)
You need to allocate memory as such,
int *n = malloc(2 * 3 * sizeof(int));
The advantage of a pointer to a dynamic array than a static array
int n[2][3];
is that the pointer can be re-used (Of course you need to take care of freeing the existing memory before resuing the pointer [If you dont have any other access paths to the memory])
reason why?
The destination area is not ensured
#include <stdlib.h>
int *p=&m[0][0];
int *n = (int*)malloc(sizeof(m));

Resources