Segmentation fault protection: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(12 intermediate revisions by 6 users not shown)
Line 19:
However, the stack being fixed at $0100-$01FF means that the stack will never overwrite the heap, yet it can get to the point where new values pushed onto the stack overwrite the old, which can cause a CPU crash if you try to unwind the stack back to the beginning.
 
The 6502 uses memory-mapping to interact with external hardware, and reading/writing a memory location you normally shouldn't because your array indexed out of bounds can cause issuesundefined withbehavior of external hardware, and even on some systems can result in a [[wp:Killer_poke|killer poke]] which can damage certain machines such as the Commodore PET. Memory-mapped ports don't work like normal memory; unlike normal memory, even ''reading'' a memory-mapped port can affect its contentsrelated hardware, or affect the contents of other ports that are related to that hardware. (This isn't a property of the 6502 itself, but of the hardware connected to it. For example, changing the video display settings of the Apple II can be done by either reading from or writing to the port associated with that setting.)
 
It's very unlikely that you'll index an array out of bounds, however, as you can only index up to 255 bytes forward from the base address. What's more likely to happen is forgetting to pop all registers you pushed before returning from a subroutine, and the program counter getting loaded with some unknown value and executing from there. Again, the 6502 won't stop you from trying to execute RAM or memory-mapped ports, and there's no guarantee what will happen (most bytes with a low nibble of 2 will crash the CPU if it tries to execute them.)
 
=={{header|68000 Assembly}}==
The closest thing the 68000 has to a segfault is an "alignment fault." <code>MOVE.W (An),Dn</code> or <code>MOVE.W (An),Dn</code> where <code>An</code> is any address register that contains an odd value will crash the CPU. More specifically, it will trigger one of the CPU's traps, forcing the program counter to jump to an error handler that is looked up from the trap table in low memory (on some machines such as the NEOGEO this just reboots the CPU. Note that byte-length commands are not subject to this aligment rule, which can lead to problems when working with structs that contain mixed data types. The programmer can avoid this very easily by either padding all their data to word length, use of the <code>EVEN</code> assembler directive after a sequence of byte-length data, or carefully arranging structs/unions so that all byte data is in pairs. An example is below:
 
<syntaxhighlight lang="68000devpac">myStruct: ;by default your assembler will ensure that labels always point to even memory locations.
dc.b $20
dc.b $40
dc.w $2222
dc.b $60
dc.b $80
dc.l $55555555
 
LEA myStruct,A0
MOVE.B (A0)+,D0
MOVE.B (A0)+,D1
MOVE.W (A0)+,D2
MOVE.B (A0)+,D3
MOVE.B (A0)+,D4
MOVE.L (A0)+,D5 ;none of these MOVE commands will cause an alignment fault.</syntaxhighlight>
 
As for executing RAM, or writing to code areas, there is no protection for either on the 68000. Failing to "balance" the stack will likely cause the alignment problem mentioned earlier, as the program counter needs to be even-aligned as well as any address registers you use.
 
(Note: Simply having an odd number stored in an address register will not crash the CPU by itself. As long as you never attempt to dereference the address register's value, no crash will occur. Otherwise you'd never be able to load byte data! As mentioned before, dereferencing an odd memory address is fine if you use a <code>.B</code> instruction to do so.
 
=={{header|Julia}}==
Most commonly, segfaults in Julia are indications of a problem in a called C library. However, the functions in Julia prefixed with
unsafe_, such as unsafe_load(), can be used to reference a null pointer as in C, and can thus cause a segfault in the LLVM compiler runtime used to run Julia:
<syntaxhighlight lang="text">julia> unsafe_load(convert(Ptr{Int}, C_NULL))
 
Exception: EXCEPTION_ACCESS_VIOLATION at 0x511008e4 -- unsafe_load at .\pointer.jl:105 [inlined]
unsafe_load at .\pointer.jl:105
...
</syntaxhighlight>
 
=={{header|Nim}}==
Nim can generates native code (using C as intermediate language) and it is possible for a program to cause a segmentation violation. Therefore the language has been designed to prevent this to happen, at least if the user doesn’t use unsafe features:
 
# Nim is a statically and strongly typed language. That means that is is possible to detect a lot of errors at compile time.
# Nim proposes a memory management model which ensures memory integrity.
# At run time Nim insures that all variables are initialized which prevents some problems.
# Nim uses copy semantic which means that an assignment copies the value instead of copying a reference. This prevents many errors related to aliasing.
# Nim generates code to check that indices are valid, that values are in a valid range, that operations do not overflow, etc. However, checking that a reference or a pointer is not nil is not done for performance reasons. This isn't really a problem, since accessing a null address instantly terminates the program (with a segmentation violation, of course). So doing a check to raise a non catchable exception would not be an improvement.
 
So far, so good, but Nim provides pragmas to deactivate the checks in some parts of the code. And it is also possible to compile the programs in “danger” mode. This way, we improve the performance but at a high price as it is no longer possible to ensure the memory integrity.
 
As a system language, Nim also provides unsafe features such as accessing the address of a variable, using type casting, deactivating the initialization of a variable, using unmanaged memory via pointers, etc. Of course, such constructions may cause memory corruption.
 
So, provided you don't use unsafe features, Nim generates code that greatly reduces the risk of a segmentation violation.
 
=={{header|Perl}}==
<!-- To all the Perl pedants out there: Yes, I have elided much extraneous detail -->
It's fairly hard to get into this kind of trouble with Perl, as it manages memory for you, etc, etc. But it can happen, and the #1 technique for keeping yourself on the straight and narrow is to start your programs off with:
 
<code>use strict;
use warnings;</code>
 
This is so important, I'm going to say it again, louder:
 
<code><b>use strict;
use warnings;</b></code>
<p>
For example, this code will segfault:
<syntaxhighlight lang="perl">unpack p,1x8</syntaxhighlight>
But with the safety features enabled you get compilation errors:
<syntaxhighlight lang="perl">use strict;
use warnings;
unpack p,1x8</syntaxhighlight>
{{out}}
<pre>Bareword "p" not allowed while "strict subs" in use at exp/SegV line 6.
Execution aborted due to compilation errors.</pre>
 
But if you absolutely feel the need to court disaster, at least run your code in an external process.
<syntaxhighlight lang="perl">qx/perl -e 'unpack p,1x8' 2>&1/ or die "Couldn't execute command\n";</syntaxhighlight>
 
=={{header|Phix}}==
Phix has extensive compilation and runtime error handling, including bounds checking, unassigned variables, invalid assignments, and more, as well as exception handling, and strives to always deliver clear human-readable and actually useful error messages along with the file name and line number where they occurred - of course within reason, as the following example shows messages triggered by inline assembly (or within prebuilt dll/so) are inherently always going to be a bit more cryptic than the norm.
<!--<langsyntaxhighlight Phixlang="phix">(notonline)-->
<span style="color: #008080;">try</span>
#ilASM{ xor eax,eax
Line 33 ⟶ 106:
<span style="color: #0000FF;">?</span><span style="color: #000000;">e</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">try</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 50 ⟶ 123:
The generated ex.err contains a full callstack and itemises in painstaking detail all variables and their values at the point of failure.
 
Note that p2js does not support exception handling (yet) or inline assembly (ever) and of course relies entirely on the browser development tools for any and all error handling and debugging capabilities - you are expected to get things working on desktop/Phix before trying to run them in a browser.
 
=={{header|Raku}}==
Barring bugs in the compiler implementation, it should be impossible to generate a seqfault in standard Raku code. Memory is automatically managed, allocated and garbage collected by the virtual machine. Arrays are automatically managed, with storage allocation autovivified on demand. Uninitialized variables default to a Nil value, which decomposes to the base type of the variable. (If a base type was not specified, it could be Any type.)
 
<syntaxhighlight lang="raku" line>my @array = [1, 2, 3, 4, 5, 6];
my $var = @array[500];
 
say $var;</syntaxhighlight>
{{out}}
<pre>(Any)</pre>
 
If you invoke the Nativecall interface and call out into C code or libraries however, all such protections are forfeit. With great power comes great responsibility.
 
 
=={{header|Wren}}==
Line 56 ⟶ 142:
 
So the example code below compiles:
<langsyntaxhighlight ecmascriptlang="wren">var myArray = [1, 2, 3, 4, 5, 6]
var myVariable = myArray[500]</langsyntaxhighlight>
but if you try to run it you get a "Subscript out of bounds" error.
 
9,476

edits