Segmentation fault with ulimit set correctly - c

I tried to help an OP on this question.
I found out that a code like the one below causes segmentation fault randomly even if the stack is set to 2000 Kbytes.
int main ()
{
int a[510000];
a[509999] = 1;
printf("%d", a[509999]);
return 0;
}
As you can see the array is 510000 x 4 bytes = 2040000 bytes.
The stack is set to 2000 Kbytes (2048000 bytes) using ulimit command:
ulimit -s 2000
ulimit -Ss 2000
Based on those numbers the application has room to store the array, but randomly it return segmentation fault.
Any ideas?

There's a few reasons why you can't do this. There are things that are already using parts of your stack.
main is not the first thing on your stack. There are functions called by the real entry point, dynamic linker, etc. that are before main and they are all probably using some of the stack.
Additionally, there can be things that are usually put on the top of the stack to set up execution. Many systems I know put all the strings in argv and all environment variables on top of the stack (which is why main is not the entry point, there's usually code that runs before main that sets up environment variables and argv for main).
And to top it off a part of the stack can be deliberately wasted to increase the randomness of ASLR if your system does that.
Run you program in the debugger, add a breakpoint at main, look up the value of the stack register and examine the memory above it (remember that most likely your stack grows down unless you're on a weird architecture). I bet you'll find lots of pointers and strings there. I just did this on a linux system and as I suspected all my environment variables were there.
The purpose of resource limits (ulimit) on Unix has never really been to micromanage things down to a byte/microsecond, they are there just to stop your program from going completely crazy and taking down the whole system with it. See them not as red lights and stop signs on a proper road, see them as run-off areas and crash barriers on a racetrack.

If you still wants to access the int location in the array, try to compile the code with out the main..this will not invoke _start
check this discussion enter link description here

Related

how to fix stack overflow error?

so, i was making this program that let people know the number of contiguous subarray which sum is equal to a certain value.
i have written the code , but when i try to run this code in vcexpress 2010, it says these error
Unhandled exception at 0x010018e7 in test 9.exe: 0xC00000FD: Stack overflow.
i have tried to search for the solution in this website and other webisites, but i can't seem to find any solution which could help me fix the error in this code(they are using recursion while i'm not).
i would be really grateful if you would kindly explain what cause this error in my code, and how to fix this error. any help would be appreciated. Thank you.
here is my code :
#include <stdio.h>
int main ()
{
int n,k,a=0,t=0;
unsigned long int i[1000000];
int v1,v2=0,v3;
scanf("%d %d",&n,&k);
for(v3=0;v3<n;v3++)
{
scanf("%d",&i[v3]);
}
do
{
for(v1=v2;v1<n;v1++)
{
t=i[v1]+t;
if(t==k)
{
a++;
break;
}
}
t=0;
v2++;
}while(v2!=n);
printf("%lu",a);
return 0;
}
Either move
unsigned long int i[1000000];
outside of main, thus making it a global variable (not an automatic one), or better yet, use some C dynamic heap allocation:
// inside main
unsigned long int *i = calloc(1000000, sizeof(unsigned long int));
if (!i) { perror("calloc"); exit(EXIT_FAILURE); };
BTW, for such a pointer, I would use (for readability reasons) some other name than i. And near the end of main you'll better free(i); to avoid memory leaks.
Also, you could move these 2 lines after the read of n and use calloc(n, sizeof(unsigned long int)) instead of calloc(1000000, sizeof(unsigned long int)) ; then you can handle arrays bigger than a million elements if your computer and system provides enough resources for that.
Your initial code is declaring an automatic variable which goes into the call frame of main on your call stack (which has a limited size, typically a megabyte or a few of them). On some operating systems there is a way to increase the size of that call stack (in an OS-specific way). BTW each thread has its own call stack.
As a rule of thumb, your C functions (including main) should avoid having call frames bigger than a few kilobytes. With the GCC compiler, you could invoke it with gcc -Wall -Wextra -Wframe-larger-than=1024 -g to get useful warnings and debug information.
Read the virtual address space wikipage. It has a nice picture worth many words. Later, find the way to query, on your operating system, the virtual address space of your process (on Linux, use proc(5) like cat /proc/$$/maps etc...). In practice, your virtual address space is likely to contain many segments (perhaps a dozen, sometimes thousands). Often, the dynamic linker or some other part of your program (or of your C standard library) uses memory-mapped files. The standard C heap (managed by malloc etc) may be organized in several segments.
If you want to understand more about virtual address space, take time to read a good book, like: Operating systems, three easy pieces (freely downloadable).
If you want to query the organization of the virtual address space in some process, you need to find an operating-system specific way to do that (on Linux, for a process of pid 1234, use /proc/1234/maps or /proc/self/maps from inside the process).
Memory is laid out much more differently than simply 4 segments(which was done long ago). The answer to the question can be generalized this way - the global or dynamically allocated memory space is handled differently than that of local variables by the system, where as the memory for local variable is limited in size, memory for dynamic allocation or global variables doesn't put a lower constraint like this.
In modern system the concept of virtual address space is there. The process from your program gets a chunk of it. That portion of memory is now responsible for holding the required memory.
Now for dynamic allocation and so on, the process can request more memory and depending on the other processes and so on, new memory request is serviced. For dynamic or global array there is no limit process wise (of course system wise there is- it cant haverequest all memory). That's why dynamic allocation or using global variable won't cause the process to run out of it's allocated memory unlike the automatic lifetime memory that it originally had for local variables.
Basically you can check your stack size
for example in Linux : ulimit -s (Kbytes)
and then decide how you manipulate your code regarding that.
As a concept I would never allocate big piece of memory on the stack because unless you know exactly the depth of your function call and the stack use, it's hard to control the precised allocated memory on stack during run time

Can you access other program's memory using program compiled with mingw?

I wrote this very simple program on Windows 8.1 and compiled it using gcc from Mingw. I ran it with "test.exe > t.txt" and "test.exe > t1.txt" and the outputs were different (even though it uses virtual addresses). It ran for a while and then it crashed. I decided to test this because I'm reading a book on operating systems.
Is it reading other programs' memory? Wasn't that not supposed to happen? I'm probably misunderstanding something...
#include <stdio.h>
int main(int argc, char *argv[]){
int r = 0;
int p[4] = {1,5,4,3};
for(r=0; p[r]!=1111111111111111; r++){
p[2] = p[r];
printf("%d\n", p[2]);
}
return 0;
}
Thank you.
SadSeven, I assume you are reading past the end of the array on purpose. What you are seeing is not other programs memory, it's uninitialized memory inside of your programs memory.
Every program runs inside it's own virtual memory space, the os's virtual memory manager takes care of this. You can't access another programs memory from your program (unless you are both using shared memory, but you have to do that on purpose)
You haven't initialized anything beyond p[3]. The C language makes no guarantees about what will happen when you try to access addresses that haven't been initiazed with data. You'll likely see a bunch of garbage, but what the garbage is isn't defined by the program you wrote. It could be anything.
The addresses you are accessing before the crash still belong to the current process, it is just unitialized memory that exists between the stack and heap.
The process probably crashed due to a segmentation fault, which occurs when a process tries to access memory that doesn't belong to it. This would be the point when it attempts to access outside its own memory.
The output you see is from reading its own memory. When it reaches memory that isn't assigned to the process it crashes.
Edit:
To make things harder for computer viruses, the starting address of a program will be different each time you run it. So you should expect different output if you run it several times. In Windows, the adress space layout is not randomized by all programs.
Your program overruns a local (auto) variable, which means that it will walk up through the stack frame(s). The stack frame contains local variables, function arguments, saved registers, the return address of the function call, and a pointer to the end of the previous stack frame. If the variables all have the same values any difference would be explained by memory addresses being different. There may be other reasons that I'm not aware of, as I'm not an expert on the memory layout in Windows.
In your code, the for loop is erroneous.
for(r=0; p[r]!=1111111111111111; r++)
it tries to access out of bound memory starting from a value of 4 of r. The result is undefined behaviour.
It may run fine till r is 1997, it may crash at r value 4, it may start playing a song from your playlist at r value 2015, even. The behaviour is not guaranteed after r value 3.
Each process runs within its separate 4GB virtual address space, attempting an out-of-bounds read won't read from another process's memory. It will read garbage from its own address space. Now, you have been asking about why the output is different, well, ASLR randomises key parts of an executable thereby giving different entry points and stack addresses at instance of a process, thereby even the same process which is run more than once will have different entry points
Read about ASLR at: http://en.wikipedia.org/wiki/Address_space_layout_randomization
Read about Virtual Memory at:
http://en.wikipedia.org/wiki/Virtual_memory

C stack odd behavior

I am using the Hope functional program on Ubuntu 14.04 with gcc 4.8.2, and doing a highly recursive function to find a large number of prime numbers. However, I get a segmentation fault: 0x000000000040e03f in reach
cell=<error reading variable: Cannot access memory at address 0x7fffff7feff8> at runtime.c:250
The segmentation fault occurs when accessing address 0x7fffff7feff8.
What the reach routine is doing is unmarking heap items that can be reached by the current expression (using a garbage collection mark-sweep). The stack is very deep (100000+ calls), but there is not a stack overflow:
base_memory = 0x7ffff35a4010
top_string = 0x7ffff35a5260
BaseHeap = 0x7ffff35a5260
heap = 0x7ffff603a450
stack = 0x7ffff72da498
TopStack = 0x7ffff7584d60
The area from base_memory to TopStack was allocated with malloc.
Whenever I get a segment violation, the address is always 0x7fffff7feff8, even with very different functions.
If you google 0x7fffff7feff8 there are quite a few entries with segment violations with this address, with no solution to the problem.
I put code into check that the heap address was in the heap range, but it never failed.
I did a gdb
find 0x7ffff35a4010,0x7ffff7584d60,0x7fffff7feff8
and nothing was found.
Why does the address 0x7fffff7feff8 show up in so many problems? Is there something amiss with the stack mechanism, or do I need to change the code in some way for the platform?
This rather looks like a stack overflow on an x86-64 system without adress space layout randomization. If the stack begins at 0x7ffffffff000, as they do on such systems, 0x7fffff7feff8 is suspiciously close to 8 MB below the beginning of the stack, which is a common default thread stack size on Linux systems.
Dump the contents of /proc/self/maps and check if the start of the stack matches this (it is listed at the bottom), and check ulimit -s to see the stack size new processes get. If /proc/self/maps lists 0x7ffffffff000 as end of the stack address range andulimit -s prints 8192, what you have is simply a stack overflow. In this event, a quick fix would be to increase the stack size of new processes (subprocesses of the active shell) like so:
ulimit -Ss size_in_kilobytes
This will work up to a hard limit root may or may not impose. In the long run, it would probably be a good idea to rewrite the code in a less excessively recursive manner.
Also, if all this hits home, you should probably enable ASLR (sysctl kernel.randomize_va_sapce=1. If that complains, your system is in dire need of an upgrade. Write kernel.randomize_va_space = 1 to /etc/sysctl.conf to make it permanent).

Possible stack size of embedded device

I am programming some embedded device which has 64 MB SDRAM. (C is used as programming language).
Is it possible to make a guess (maybe even a rough guess) about the possible size of the stack of this device?
Referring to memory which gets used when we make allocations such as, e.g.,
char s[100];
int t[50];
etc.
e.g., will it be more than 50KB? etc. that is what I mean with rough
plus when I have variables inside some function f
f()
{
int p;
}
when f() exists, this variable dies right?
So when I call f2():
void f2()
{
char t[100];
}
Only the size of a 100 element char array will be added to the stack size right??
size of int p from previous function is not considered anymore.
All sorts of guesses can be made :) Most (all?) embedded development environments provide mechanisms for allocating device memories (read-only, stack, heap, etc.) This is commonly done through linker directive files or C #pragmas placed in a setup source file. Without more information on your development environment, no accurate guess can be made.
In function f(), variable p will exist on the stack. When the function exits, that location on the stack will likely be used for something else.
As for function f2(), you can expect that 100 bytes from the stack will be assigned to t while this function is executing. The size of p will not be considered.
Note that the stack can be used for other information, so you cannot reliably estimate stack usage without considering other factors. For example, do you expect recursion? The stack can be used to store function call/return information - thereby reducing the amount of space you have for local (stack) variables.
Lastly, I've worked with devices operating with less than 1KB of stack, so assumptions should be made carefully.
your question looks like ,"Guessing the stack size"
Why guess when you can know it exactly its not from the sky ! :)
For an embedded programmer the stack size is always his in hands,one has to handle it through the linker command file that he submit to a loader
some thing like this as below
Linker.cmd
MEMORY
{
.
.
SARAM2 (RWIX) : origin = 0x039000, length = 0x010000 /*64KB*/
.
.
}
SECTIONS
{
.
.
.stack > SARAM2
.sysstack > SARAM2
.
.
}
so its clear that you can set your own stack size provided "the stack size is limited to stack pointer bound"
so it is completely depends on your stack pointer range, if your stack pointer is 16bit you stack size is limited to 2^16 which is 64KB
for instance moving away from firmware programming, in a standard linux machine also
if you go for typing
ulimit -a
you will get your limited stack size,and its extendable up to the boundary where Stack Pointer can point to
BTW These may further help you
Direction of Stack Growth
When Does Stack Really Over Flow
and i also suggest its not a bad idea to monitor your stack size , in other words trying to find Stack pointer value which can make you clear 'what is your stack status ?', especially for an embedded programmer a stack overflow cause severe damage :)
There is a script in the Linux kernel sources that can help you find the functions that heavily allocate on the stack. The script is named checkstack.pl and is located in the scripts directory.
Here is a sample invocation:
$ objdump -d $BUILDDIR/target-isns | perl checkstack.pl x86_64
0x00403799 configfs_handle_events []: 4384
0x004041d6 isns_attr_query []: 4176
0x00404646 isns_target_register []: 4176
The script displays the functions that consumes the most space on the stack. The script can help you make a guess for the stack size required. Also, it helps you determine which functions should be optimized with regard to their stack usage.
You may find that your linker is capable of performing stack requirement analysis - normally by command line option to specify map file content. If you could add information about your toolchain, you will get better advice.
What such analysis gives you is the worst case stack usage and the call path involved for any particular function - for the process total you need to look at the stack usage for main() and any other thread entry points (each of which will have a separate stack). You may need also to consider ISRs which on some targets may use the interrupted process or thread stack, on others there may be a separate interrupt stack.
What linker stack analysis cannot determine is stack usage in the case of recursion or call through function pointers, both of which depend on the prevailing runtime conditions that cannot be determined statically.

At what point does the segfault occur?

Does the following code segfault at array[10] = 22 or array[9999] = 22?
I'm just trying to figure out if the whole code would execute before it seg faults. (in the C language).
#include <stdio.h>
int main(){
int array[10];
int i;
for(i=0; i<9999; ++i){
array[i] = 22;
}
return 0;
}
It depends...
If the memory after array[9] is clean then nothing might happen, until ofcourse one reaches a segment of memory which is occupied.
Try out the code and add:
printf("%d\n",i);
in the loop and you will see when it crashes and burns.
I get various results, ranging from 596 to 2380.
Use a debugger?
$ gcc -g seg.c -o so_segfault
$ gdb so_segfault
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) run
Starting program: /.../so_segfault
Program received signal SIGSEGV, Segmentation fault.
0x080483b1 in main () at seg.c:7
7 array[i] = 22;
(gdb) print i
$1 = 2406
(gdb)
In fact if you run this again, you will see that the segfault will not always occur for the same value of i. What is sure is that it happens when i>=10, but there is no way to determine the value for i for which it will crash, because this is not deterministic: It depends on how the memory is allocated. If the memory is free until array[222] (aka no other programs use it), it will go on until i=222, but it might as well crash for any other value of i>=10.
The answer is maybe. The C language says nothing about what should happen in this case. It is undefined behavior. The compiler is not required to detect the problem, do anything to handle the problem, terminate the program or anything else. And so it does nothing.
You write to memory that's not yours, and in practice one of three things may happen:
You might be lucky, and just get a segfault. This happens if you hit an address that is not allocated to your process. The OS will detect this, and throw an error at you.
You might hit memory that's genuinely unused, in which case no error will occur right away. But if the memory is allocated and used later, it will overwrite your data, and if you expect it to still be there by then, you'll get some nice delayed-action errors.
You might hit data that's actually used for something else already. You overwrite that, and sometime soon, when the original data is needed, it'll read your data instead, and unpredictable errors will ensue.
Writing out of bounds: Just don't do it. The C language won't do anything to tell you when it happens, so you have to keep an eye on it yourself.
When and if your code crashes is not deterministic. It'll depend on what platform you're running the code on.
array is a stack variable, so your compiler is going to reserve 10 * sizeof(int) bytes on the stack for it. Depending on how the compiler arranges other local variables and which way your stack grows, i may come right after array. If you follow Daniel's suggestion and put the printf statement in, you may notice an interesting effect. On my platform, when i = 10, array[10] = 22 clobbers i and the next assignment is to array[23].
A segmentation violation occurs when user code tries to touch a page that it does not have access to. In this case, you'll get one if your stack is small enough that 9999 iterations runs out off the stack.
If you had allocated array on the heap instead (by using malloc()), then you'll get a SIGSEGV when you run off the end of a page boundary. Even a 10 byte allocation will return a whole page. Page sizes vary by platform. Note that some malloc debuggers can try to flag an array out-of-bounds case, but you won't get the SIGSEGV unless the hardware gets involved when you run off the end of the page.
Where your code will segfault depends on what compiler you're using, luck, and other linking details of the program in question. You will most likely not segfault for i == 10. Even though that is outside your array, you will almost certainly still have memory allocated to your process at that location. As you keep going beyond your array bounds, however, you will eventually leave the memory allocated to your process and then take a segfault.
However, if you write beyond an array boundary, you will likely overwrite other automatic variables in your same stack frame. If any of these variables are pointers (or array indexes used later), then when you reference these now-corrupted values, you'll possibly take a segfault. (Depending on the exact value corrupted to and whether or not you're now going to reference memory that is not allocated to your process.)
This is not terribly deterministic.
segmentation fault happens when accessing outside of the processes dedicated memory,
this is not easily predicted. When i == 10 it's outside the array.. but might still be in the memory of the process. This depends how the processes memory got allocated, something there is no way (normally) of knowing (depending of the memory manager of the OS). So segfault might happen at any of i = 10 - 9999, or not at all.
I suggest using GDB to investigate such problems: http://www.gnu.org/software/gdb/documentation/
More generally, you can figure out where the segmentation fault occurs in Linux systems by using a debugger. For example, to use gdb, compile your program with debugging symbols by using the -g flag, e.g.:
gcc -g segfault.c -o segfault
Then, invoke gdb with your program and any arguments using the --args flag, .g.:
gdb --args ./segault myarg1 myarg2 ...
Then, when the debugger starts up, type run, and your program should run until it receives SIGSEGV, and should tell you where it was in the source code when it received that signal.

Resources