How to stop segmentation fault (core dumped)? - c

I am trying to learn c, but everytime i run a code that needs user imput i get segfault error
My os is arch linux
it was compiled with "gcc -o test1 test1.c"
Appearently it happens because the program cannot allocate memory, but none of the tutorials i saw did any extra thing.
here is the code i was trying to run:
#include<stdio.h>
int main(){
int age;
scanf("%d", age);
printf("age = %d", age);
return 0;
}
and when i run it with ./test1 i get 19315 segmentation fault (core dumped) ./test
I tried looking it up on google and found nothing that solved this

scanf() expects its arguments (except the first one, which is the format string) to point at the memory where values are to be stored. It is trying to store the user input into whatever memory age points at when interpreted as a pointer, and it doesn't have permission to write there, so it segfaults. To fix the segfault, add the address-of operator in front of age in the scanf() invocation:
scanf("%d", &age);
This way scanf will store the integer into age instead of writing into whatever address it thinks is in age.

Nathan is correct about the fix (scanf("%d", &age)), but it could be useful to go into a bit more detail as to exactly what's happening here.
Segfaults don't happen when the program can't allocate memory (and you should avoid whatever tutorial told you otherwise). Rather, they happen when your program tries to access memory that it doesn't have permission (from the operating system) to access. (1) (This keeps a normal user's programs from reading confidential information from other users' programs, among other things.)
So what was happening in your code was the following:
int age; declares an int named age and claims some space on the stack for it to go. You don't initialize it, so age contains whatever happens to live in that memory already. Let's assume it's 42.
scanf("%d", age); tries to read an int from stdin, then put it at the location pointed to by age. age isn't actually a pointer, but pointers are (to first approximation) just numbers representing an address, so scanf gleefully attempts to write to address 42. (gcc really should have warned you about this; I'm not sure why it didn't.)
Your program doesn't have permission to access address 42, so you get the segfault.
(1) There are a few ways to get a segfault as an indirect result of running out of memory: if you declare a gigantic array as a local variable, it can overflow the stack (the memory allocated for locals) and try to read whatever's on the other end; that might lead to a segfault depending on what's there. And if you malloc some memory, malloc fails (and returns NULL), and you don't check the return code, then trying to read the NULL you got from malloc will generally cause a segfault. But it's always the access attempt that actually causes the segfault.

Related

Why it is compiling it as an infinite loop instead for finite one? [duplicate]

I had gone to an interview in which I was asked the question:
What do you think about the following?
int i;
scanf ("%d", i);
printf ("i: %d\n", i);
I responded:
The program will compile successfully.
It will print the number incorrectly but it will run till the end
without crashing
The response that I made was wrong. I was overwhelmed.
After that they dismissed me:
The program would crash in some cases and lead to an core dump.
I could not understand why the program would crash? Could anyone explain me the reason? Any help appreciated.
When a variable is defined, the compiler allocates memory for that variable.
int i; // The compiler will allocate sizeof(int) bytes for i
i defined above is not initialized and have indeterminate value.
To write data to that memory location allocated for i, you need to specify the address of the variable. The statement
scanf("%d", &i);
will write an int data by the user to the memory location allocated for i.
If & is not placed before i, then scanf will try to write the input data to the memory location i instead of &i. Since i contains indeterminate value, there are some possibilities that it may contain a value equivalent to the value of a memory address or it may contain a value which is out of range of memory address.
In either case, the program may behave erratically and will lead to undefined behavior. In that case anything could happen.
Beacuse it invokes undefined behavior. The scanf() family of functions expect a pointer to an integer when the "%d" specifier is found. You are passing an integer which can be interpreted as the address of some integer but it's not. This doesn't have a defined behavior in the standard. It will compile indeed (will issue some warning however) but it will certainly work in an unexpected way.
In the code as is, there is yet another problem. The i variable is never initialized so it will have an indeterminate value, yet another reason for Undefined Behavior.
Note that the standard doesn't say anything about what happens when you pass a given type when some other type was expected, it's simply undefined behavior no matter what types you swap. But this particular situation falls under a special consideration because pointers can be converted to integers, though the behavior is only defined if you convert back to a pointer and if the integer type is capable of storing the value correctly. This is why it compiles, but it surely does not work correctly.
You passed data having the wrong type (int* is expected, but int is passed) to scanf(). This will lead to undefined behavior.
Anything can happen for undefined behavior. The program may crash and may not crash.
In a typical environment, I guess the program will crash when some "address" which points to a location which isn't allowed to write into by the operating system is passed to scanf(), and writing to there will have the OS terminate the application program, and it will be observed as a crash.
One thing that the other answers haven't mentioned yet is that on some platforms, sizeof (int) != sizeof (int*). If the arguments are passed in a certain way*, scanf could gobble up part of another variable, or of the return address. Changing the return address could very well lead to a security vulnerability.
* I'm no assembly language expert, so take this with a grain of salt.
I could not understand why the program would crash? Could anyone explain me the reason. Any help appreciated.
Maybe a little more applied:
int i = 123;
scanf ("%d", &i);
With the first command you allocate memory for one integer value and write 123 in this memory block. For this example let's say this memory block has the address 0x0000ffff. With the second command you read your input and scanf writes the input to memory block 0x0000ffff - because you are not accessing (dereferencing) the value of this variable i but it's address.
If you use the command scanf ("%d", i); instead you are writing the input to the memory address 123 (because that's the value stored inside this variable). Obviously that can go terribly wrong and cause a crash.
Since there is no &(ampersand) in scanf(as required by the standard), so as soon as we enter the value the program will terminate abruptly, no matter how many lines of code are written further in the program.
-->> I executed and found that in code blocks.
Same program if we run in turbo c compiler then it will run perfectly all the lines even which are after scanf, but the only thing, as we know the value of i printed would be garbage.
Conclusion:- Since at some compiler it will run and at some it would not, so this is not a valid program.

Under what circumstances does a segmentation fault occur? [duplicate]

What is a segmentation fault? Is it different in C and C++? How are segmentation faults and dangling pointers related?
Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” It’s a helper mechanism that keeps you from corrupting the memory and introducing hard-to-debug memory bugs. Whenever you get a segfault you know you are doing something wrong with memory – accessing a variable that has already been freed, writing to a read-only portion of the memory, etc. Segmentation fault is essentially the same in most languages that let you mess with memory management, there is no principal difference between segfaults in C and C++.
There are many ways to get a segfault, at least in the lower-level languages such as C(++). A common way to get a segfault is to dereference a null pointer:
int *p = NULL;
*p = 1;
Another segfault happens when you try to write to a portion of memory that was marked as read-only:
char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault
Dangling pointer points to a thing that does not exist anymore, like here:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
The pointer p dangles because it points to the character variable c that ceased to exist after the block ended. And when you try to dereference dangling pointer (like *p='A'), you would probably get a segfault.
It would be worth noting that segmentation fault isn't caused by directly accessing another process memory (this is what I'm hearing sometimes), as it is simply not possible. With virtual memory every process has its own virtual address space and there is no way to access another one using any value of pointer. Exception to this can be shared libraries which are same physical address space mapped to (possibly) different virtual addresses and kernel memory which is even mapped in the same way in every process (to avoid TLB flushing on syscall, I think). And things like shmat ;) - these are what I count as 'indirect' access. One can, however, check that they are usually located long way from process code and we are usually able to access them (this is why they are there, nevertheless accessing them in a improper way will produce segmentation fault).
Still, segmentation fault can occur in case of accessing our own (process) memory in improper way (for instance trying to write to non-writable space). But the most common reason for it is the access to the part of the virtual address space that is not mapped to physical one at all.
And all of this with respect to virtual memory systems.
A segmentation fault is caused by a request for a page that the process does not have listed in its descriptor table, or an invalid request for a page that it does have listed (e.g. a write request on a read-only page).
A dangling pointer is a pointer that may or may not point to a valid page, but does point to an "unexpected" segment of memory.
To be honest, as other posters have mentioned, Wikipedia has a very good article on this so have a look there. This type of error is very common and often called other things such as Access Violation or General Protection Fault.
They are no different in C, C++ or any other language that allows pointers. These kinds of errors are usually caused by pointers that are
Used before being properly initialised
Used after the memory they point to has been realloced or deleted.
Used in an indexed array where the index is outside of the array bounds. This is generally only when you're doing pointer math on traditional arrays or c-strings, not STL / Boost based collections (in C++.)
According to Wikipedia:
A segmentation fault occurs when a
program attempts to access a memory
location that it is not allowed to
access, or attempts to access a memory
location in a way that is not allowed
(for example, attempting to write to a
read-only location, or to overwrite
part of the operating system).
Segmentation fault is also caused by hardware failures, in this case the RAM memories. This is the less common cause, but if you don't find an error in your code, maybe a memtest could help you.
The solution in this case, change the RAM.
edit:
Here there is a reference: Segmentation fault by hardware
Wikipedia's Segmentation_fault page has a very nice description about it, just pointing out the causes and reasons. Have a look into the wiki for a detailed description.
In computing, a segmentation fault (often shortened to segfault) or access violation is a fault raised by hardware with memory protection, notifying an operating system (OS) about a memory access violation.
The following are some typical causes of a segmentation fault:
Dereferencing NULL pointers – this is special-cased by memory management hardware
Attempting to access a nonexistent memory address (outside process's address space)
Attempting to access memory the program does not have rights to (such as kernel structures in process context)
Attempting to write read-only memory (such as code segment)
These in turn are often caused by programming errors that result in invalid memory access:
Dereferencing or assigning to an uninitialized pointer (wild pointer, which points to a random memory address)
Dereferencing or assigning to a freed pointer (dangling pointer, which points to memory that has been freed/deallocated/deleted)
A buffer overflow.
A stack overflow.
Attempting to execute a program that does not compile correctly. (Some compilers will output an executable file despite the presence of compile-time errors.)
Segmentation fault occurs when a process (running instance of a program) is trying to access read-only memory address or memory range which is being used by other process or access the non-existent (invalid) memory address.
Dangling Reference (pointer) problem means that trying to access an object or variable whose contents have already been deleted from memory, e.g:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
In simple words: segmentation fault is the operating system sending a signal to the program
saying that it has detected an illegal memory access and is prematurely terminating the program to prevent
memory from being corrupted.
There are several good explanations of "Segmentation fault" in the answers, but since with segmentation fault often there's a dump of the memory content, I wanted to share where the relationship between the "core dumped" part in Segmentation fault (core dumped) and memory comes from:
From about 1955 to 1975 - before semiconductor memory - the dominant technology in computer memory used tiny magnetic doughnuts strung on copper wires. The doughnuts were known as "ferrite cores" and main memory thus known as "core memory" or "core".
Taken from here.
"Segmentation fault" means that you tried to access memory that you do not have access to.
The first problem is with your arguments of main. The main function should be int main(int argc, char *argv[]), and you should check that argc is at least 2 before accessing argv[1].
Also, since you're passing in a float to printf (which, by the way, gets converted to a double when passing to printf), you should use the %f format specifier. The %s format specifier is for strings ('\0'-terminated character arrays).
Simple meaning of Segmentation fault is that you are trying to access some memory which doesn't belong to you. Segmentation fault occurs when we attempt to read and/or write tasks in a read only memory location or try to freed memory. In other words, we can explain this as some sort of memory corruption.
Below I mention common mistakes done by programmers that lead to Segmentation fault.
Use scanf() in wrong way(forgot to put &).
int num;
scanf("%d", num);// must use &num instead of num
Use pointers in wrong way.
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
Modifying a string literal(pointer try to write or modify a read only memory.)
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
Try to reach through an address which is already freed.
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
Stack Overflow -: Running out of memory on the stack
Accessing an array out of bounds'
Use wrong format specifiers when using printf() and scanf()'
Consider the following snippets of Code,
SNIPPET 1
int *number = NULL;
*number = 1;
SNIPPET 2
int *number = malloc(sizeof(int));
*number = 1;
I'd assume you know the meaning of the functions: malloc() and sizeof() if you are asking this question.
Now that that is settled,
SNIPPET 1 would throw a Segmentation Fault Error.
while SNIPPET 2 would not.
Here's why.
The first line of snippet one is creating a variable(*number) to store the address of some other variable but in this case it is initialized to NULL.
on the other hand,
The second line of snippet two is creating the same variable(*number) to store the address of some other and in this case it is given a memory address(because malloc() is a function in C/C++ that returns a memory address of the computer)
The point is you cannot put water inside a bowl that has not been bought OR a bowl that has been bought but has not been authorized for use by you.
When you try to do that, the computer is alerted and it throws a SegFault error.
You should only face this errors with languages that are close to low-level like C/C++. There is an abstraction in other High Level Languages that ensure you do not make this error.
It is also paramount to understand that Segmentation Fault is not language-specific.
There are enough definitions of segmentation fault, I would like to quote few examples which I came across while programming, which might seem like silly mistakes, but will waste a lot of time.
You can get a segmentation fault in below case while argument type mismatch in printf:
#include <stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
output : Segmentation Fault (SIGSEGV)
When you forgot to allocate memory to a pointer, but try to use it.
#include <stdio.h>
typedef struct{
int a;
} myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
output : Segmentation Fault (SIGSEGV)
In computing, a segmentation fault or access violation is a fault, or failure condition, raised by hardware with memory protection,
notifying an operating system the software has attempted to access a
restricted area of memory. -WIKIPEDIA
You might be accessing the computer memory with the wrong data type. Your case might be like the code below:
#include <stdio.h>
int main(int argc, char *argv[]) {
char A = 'asd';
puts(A);
return 0;
}
'asd' -> is a character chain rather than a single character char data type. So, storing it as a char causes the segmentation fault. Stocking some data at the wrong position.
Storing this string or character chain as a single char is trying to fit a square peg in a round hole.
Terminated due to signal: SEGMENTATION FAULT (11)
Segm. Fault is the same as trying to breath in under water, your lungs were not made for that. Reserving memory for an integer and then trying to operate it as another data type won't work at all.
Segmentation fault occurs when a process (running instance of a program) is trying to access a read-only memory address or memory range which is being used by another process or access the non-existent memory address.
seg fault,when type gets mismatched
A segmentation fault or access violation occurs when a program attempts to access a memory location that is not exist, or attempts to access a memory location in a way that is not allowed.
/* "Array out of bounds" error
valid indices for array foo
are 0, 1, ... 999 */
int foo[1000];
for (int i = 0; i <= 1000 ; i++)
foo[i] = i;
Here i[1000] not exist, so segfault occurs.
Causes of segmentation fault:
it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.
De-referencing NULL pointers – this is special-cased by memory management hardware.
Attempting to access a nonexistent memory address (outside process’s address space).
Attempting to access memory the program does not have rights to (such as kernel structures in process context).
Attempting to write read-only memory (such as code segment).

What will happen if '&' is not put in a 'scanf' statement?

I had gone to an interview in which I was asked the question:
What do you think about the following?
int i;
scanf ("%d", i);
printf ("i: %d\n", i);
I responded:
The program will compile successfully.
It will print the number incorrectly but it will run till the end
without crashing
The response that I made was wrong. I was overwhelmed.
After that they dismissed me:
The program would crash in some cases and lead to an core dump.
I could not understand why the program would crash? Could anyone explain me the reason? Any help appreciated.
When a variable is defined, the compiler allocates memory for that variable.
int i; // The compiler will allocate sizeof(int) bytes for i
i defined above is not initialized and have indeterminate value.
To write data to that memory location allocated for i, you need to specify the address of the variable. The statement
scanf("%d", &i);
will write an int data by the user to the memory location allocated for i.
If & is not placed before i, then scanf will try to write the input data to the memory location i instead of &i. Since i contains indeterminate value, there are some possibilities that it may contain a value equivalent to the value of a memory address or it may contain a value which is out of range of memory address.
In either case, the program may behave erratically and will lead to undefined behavior. In that case anything could happen.
Beacuse it invokes undefined behavior. The scanf() family of functions expect a pointer to an integer when the "%d" specifier is found. You are passing an integer which can be interpreted as the address of some integer but it's not. This doesn't have a defined behavior in the standard. It will compile indeed (will issue some warning however) but it will certainly work in an unexpected way.
In the code as is, there is yet another problem. The i variable is never initialized so it will have an indeterminate value, yet another reason for Undefined Behavior.
Note that the standard doesn't say anything about what happens when you pass a given type when some other type was expected, it's simply undefined behavior no matter what types you swap. But this particular situation falls under a special consideration because pointers can be converted to integers, though the behavior is only defined if you convert back to a pointer and if the integer type is capable of storing the value correctly. This is why it compiles, but it surely does not work correctly.
You passed data having the wrong type (int* is expected, but int is passed) to scanf(). This will lead to undefined behavior.
Anything can happen for undefined behavior. The program may crash and may not crash.
In a typical environment, I guess the program will crash when some "address" which points to a location which isn't allowed to write into by the operating system is passed to scanf(), and writing to there will have the OS terminate the application program, and it will be observed as a crash.
One thing that the other answers haven't mentioned yet is that on some platforms, sizeof (int) != sizeof (int*). If the arguments are passed in a certain way*, scanf could gobble up part of another variable, or of the return address. Changing the return address could very well lead to a security vulnerability.
* I'm no assembly language expert, so take this with a grain of salt.
I could not understand why the program would crash? Could anyone explain me the reason. Any help appreciated.
Maybe a little more applied:
int i = 123;
scanf ("%d", &i);
With the first command you allocate memory for one integer value and write 123 in this memory block. For this example let's say this memory block has the address 0x0000ffff. With the second command you read your input and scanf writes the input to memory block 0x0000ffff - because you are not accessing (dereferencing) the value of this variable i but it's address.
If you use the command scanf ("%d", i); instead you are writing the input to the memory address 123 (because that's the value stored inside this variable). Obviously that can go terribly wrong and cause a crash.
Since there is no &(ampersand) in scanf(as required by the standard), so as soon as we enter the value the program will terminate abruptly, no matter how many lines of code are written further in the program.
-->> I executed and found that in code blocks.
Same program if we run in turbo c compiler then it will run perfectly all the lines even which are after scanf, but the only thing, as we know the value of i printed would be garbage.
Conclusion:- Since at some compiler it will run and at some it would not, so this is not a valid program.

what happens to array elements after the original array is reallocated?

#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a;
a = (int *)malloc(100*sizeof(int));
int i=0;
for (i=0;i<100;i++)
{
a[i] = i+1;
printf("a[%d] = %d \n " , i,a[i]);
}
a = (int*)realloc(a,75*sizeof(int));
for (i=0;i<100;i++)
{
printf("a[%d] = %d \n " , i,a[i]);
}
free(a);
return 0;
}
In this program I expected the program to give me a segmentation fault because im trying to access an element of an array which is freed using realloc() . But then the output is pretty much the same except for a few final elements !
So my doubt is whether the memory is actually getting freed ? What exactly is happening ?
The way realloc works is that it guarantees that a[0]..a[74] will have the same values after the realloc as they did before it.
However, the moment you try to access a[75] after the realloc, you have undefined behaviour. This means that the program is free to behave in any way it pleases, including segfaulting, printing out the original values, printing out some random values, not printing anything at all, launching a nuclear strike, etc. There is no requirement for it to segfault.
So my doubt is whether the memory is actually getting freed?
There is absolutely no reason to think that realloc is not doing its job here.
What exactly is happening?
Most likely, the memory is getting freed by shrinking the original memory block and not wiping out the now unused final 25 array elements. As a result, the undefined behaviour manifests itself my printing out the original values. It is worth noting that even the slightest changes to the code, the compiler, the runtime library, the OS etc could make the undefined behaviour manifest itself differently.
You may get a segmentation fault, but you may not. The behaviour is undefined, which means anything can happen, but I'll attempt to explain what you might be experiencing.
There's a mapping between your virtual address space and physical pages, and that mapping is usually in pages of 4096 bytes at least (well, there's virtual memory also, but lets ignore that for the moment).
You get a segmentation fault if you attempt to address virtual address space that doesn't map to a physical page. So your call to realloc may not have resulted in a physical page being returned to the system, so it's still mapped to you program and can be used. However a following call to malloc could use that space, or it could be reclaimed by the system at any time. In the former case you'd possibly overwrite another variable, in the latter case you'll segfault.
Accessing an array beyond its bounds is undefined behaviour. You might encounter a runtime error. Or you might not. The memory manager may well have decided to re-use the original block of memory when you re-sized. But there's no guarantee of that. Undefined behaviour means that you cannot reason about or predict what will happen. There's no grounds for you to expect anything to happen.
Simply put, don't access beyond the end of the array.
Some other points:
The correct main declaration here is int main(void).
Casting the value returned by malloc is not needed and can mask errors. Don't do it.
Always store the return value of realloc into a separate variable so that you can detect NULL being returned and so avoid losing and leaking the original block.

Expected segmentation fault, as soon as assigning a value to index 1?

In the code snippet, I expected a segmentation fault as soon as trying to assign a value to count[1]. However the code continues and executes the second for-loop, only indicating a segmentation fault when the program terminates.
#include <stdio.h>
int main()
{
int count[1];
int i;
for(i = 0; i < 100; i++)
{
count[i] = i;
}
for(i = 0; i < 100; i++)
{
printf("%d\n", count[i]);
}
return 0;
}
Could someone explain what is happening?
Reasons for edit:
Improved the example code as per comments of users,
int count[0] -> int count[1],
too avoid flame wars.
You're writing beyond the bounds of the array. That doesn't mean you're going to get a segmentation fault. It just means that you have undefined behavior. Your program's behavior is no longer constrained by the C standard. Anything could happen (including the program seeming to work) -- a segfault is just one possible outcome.
In practice, a segmentation fault occurs when you try to access a memory page that is not mapped to your process by the OS. Each page is 4KB on a typical x86 PC, so basically, your process is given access to memory in 4KB chunks, and you only get a segfault if you write outside the current chunk.
With the small indices you're using, you're still staying within the current memory page, which is allocated to your process, and so the CPU doesn't detect that you're accessing memory out of bounds.
When you write beyond the array bounds, you are probably still writing data into the area of memory under the control of your process; you are also almost certainly overwriting memory used by other software, such as heap or stack frame management code. It is only when that code executes, such as when the current function attempts to return, that your code might go awry. Actually, you really hope for a seg fault.
Your code is broken:
seg.c:5: warning: ISO C forbids zero-size array ‘count’
Always compile with high warning levels, for example -Wall -pedantic for GCC.
Edit:
What you are effectively doing is corrupting mains function stack frame. Since stack nowadays pretty much always grows down, this is what's happening:
First loop overrides stack memory holding main parameters and return address to crt0 routines.
Second loop happily reads that memory.
When main returns the segmentation fault is triggered since return address is fubar-ed.
This is a classic case of buffer overrun and is the basis of many network worms.
Run the program under the debugger and check the addresses of local variables. In GDB you can say set backtrace past-main so backtrace would show you all the routines leading to main.
By the way, the same effect could be achieved without zero-length array - just make its size smaller then number of loop iterations.

Resources