Napište nejkratší kód, který vyvolá Segmentation Fault (SIGSEGV) v libovolném programovacím jazyce.
Komentáře
- Páni. Možná nejkratší úspěšná otázka.
- @MatthewRoh Ze zájmu jsem vytvořil tento dotaz SEDE. Vypadá to, že jich je pár s +10 nebo vyšším, ale toto je první nad +40
Odpověď
C, 5 znaků
main;
Je to deklarace proměnné – int
typ je implicitní (funkce zkopírována z Jazyk B) a 0
je výchozí hodnota. Při spuštění se pokusí provést číslo (čísla nejsou spustitelná) a způsobí SIGSEGV
.
Komentáře
- @Macmade: Ve skutečnosti je to
0
.static
proměnné začínají jako0
amain;
jestatic
, jak jsem prohlásil mimo funkci. c-faq.com/decl/initval.html - když jsem si s touto věcí naposledy hrál, přišel jsem na to, že ‚ je jiný důvod pro segfault. Nejprve voláním main přeskočíte na umístění main, ne na hodnotu, další věc je
main
je int, to ‚ s umístěn v.bss
, obvykle jsou funkce umístěny v.text
, když jádro načte program elf, vytvoří spustitelnou stránku pro.text
a neproveditelné pro.bss
, takže voláním main přejdete na nespustitelnou stránku a provedení něčeho na takové stránce je chyba ochrany. - Ano, segfaults v C jsou skoro výchozí: P
-
main __attribute__((section(".text#")))=0xc3;
FTFY (alespoň se zdá, že se vrátí bez narazil na můj x86). - @jozxyqk Nebo kratší,
const main=195;
. Jak zajímavé je, že ‚ to funguje, cílem této výzvy golfového kódu bylo udělat kód segfault, nikoli fungovat :).
Odpověď
Bash, 11
kill -11 $$
Komentáře
- Signál 11 v 11 znacích. Vypadá to, že je to legitimní.
- @ nyuszika7h Chtěl jsem váš komentář podpořit, ale právě teď máte 11 hlasujících, takže ‚ to nechám tak. : P
- @AlexL. Zdá se, že to ostatní pokazili 🙁
- @theonlygusti Jo … To je ‚ příliš špatné. 🙁 No, pak to teď mohu hlasovat. .
- Až 42 hlasů, žádný kontakt!
Odpověď
Sestava (Linux , x86-64), 1 bajt
RET
Tento kód segfaults.
Komentáře
- Jako soubor MSDOS .com se spouští a končí bez chyby.
- Moje myšlenka je: pouze zadání „assembly“ není ‚ natolik, aby nastavit jako výchozí.
- @JB: V systému MS DOS žádný program nikdy nevytvoří chybu segmentace. To ‚ s, protože systém MS DOS běží v reálném režimu, kde ochrana paměti neexistuje.
- @celtschk IIRC NTVDM se bude zobrazovat na neexistujících adresách a těch, které nejsou přiděleny systému MS-DOS.
- @celtschk: Můžete to stejně nastavit takto: mov bx, 1000h; shr ebx, 4; mov eax, [ebx] – > CPU raise je základním SEGV (AFAIK tam ‚ není nikdo, kdo by to zvládl).
Odpovědět
Python 2, 13
exec"()"*7**6
Windows hlásí chybový kód c00000fd (Stack Overflow), který bych předpokládal jako podtyp chyba segmentace.
Díky Alexovi A. a Megovi je potvrzeno, že způsobí poruchy segmentace také v systémech Mac a Linux. Python je jazyk volby pro přenosné havárie vašich programů.
Komentáře
-
Segmentation fault: 11
na počítačích Mac -
Segmentation fault (core dumped)
v systému Linux - Zavěsí to jako první?
- @MegaMan Jak dlouho trvá dokončení ? Ne, 7 ** 6 je jen asi 100 kB, takže ‚ není znatelné zpoždění.
- @MaxGasner Zkuste si znovu přečíst programovací jazyk 🙂
Odpovědět
pdfTeX ( 51)
\def~#1{\meaning}\write0{\expandafter~\string}\bye
Toto je ve skutečnosti pravděpodobně chyba , ale není v původní TeX, napsaný Knuthem: kompilace kódu s tex filename.tex
místo pdftex filename.tex
nevytváří segfault.
odpověď
LOLCODE, 4 bajty
OBTW
nefunguje online, pouze v tlumočníku C.
Komentáře
- LOL FANCY CODE M8 8/8 KTHXBYE
Odpověď
Python, 33 znaků
>>> import ctypes;ctypes.string_at(0) Segmentation fault
Zdroj: http://bugs.python.org/issue1215#msg143236
Python, 60 znaků
>>> import sys;sys.setrecursionlimit(1<<30);f=lambda f:f(f);f(f) Segmentation fault
Zdroj: http://svn.python.org/view/python/trunk/Lib/test/crashers/recursive_call.py?view=markup
Toto je verze Pythonu n Testuji na:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) [GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Tlumočník Pythonu se obecně těžko zhroutí, ale výše uvedené je selektivní zneužívání …
Odpověď
Další – 3 znaky
0 @
(@
je načítání)
Komentáře
- Dosud nejkratší, který bude fungovat na moderních systémech.
- Který dále? Gforth jen říká “ Neplatná adresa paměti “
odpověď
Spustitelný soubor W32 .com – 0 bajtů
To se bude zdát divné, ale na 32bitových systémech Windows může vytvoření a spuštění prázdného souboru .com může způsobit segfault, v závislosti na … něčem. DOS to pouze přijímá (8086 nemá správu paměti, neexistují žádné smysluplné segmenty) a 64bitový Windows jej odmítá spustit (x86-64 bez režimu v86, ve kterém lze spustit soubor .com).
Odpověď
C, 18
main(){raise(11);}
Komentáře
- musíte do seznamu kódů přidat #include < signal.h >?
- @FlorianCastellane: v C90 a nižší, pro jakékoli volání funkce provedené bez viditelné deklarace, kompilátor implicitně deklaruje jako
int func()
. tj. funkce vracejícíint
s nespecifikovanými parametry. V tomto případě jeraise
funkce, která vrací int a přijímá argument int, takže to vyjde (i když si kompilátor stěžuje). - @Hasturkun
main(){main();}
odpověď
Perl (< 5.14), 9 znaků
/(?{??})/
V 5.14 byl regex engine reentrantní, takže nemohl být takto havarován, ale 5.12 a dříve se segfault, pokud to zkusíte.
Komentáře
- Mohu to reprodukovat na Perlu 5.14 (Debian) a 5.18 (Arch Linux). sprunge.us/RKHT
- Reprodukováno s Perl v5.20.2 (Windows)
- A co
/(?R)/
ve starších verzích Perlu?
odpověď
brainfuck (2)
<.
Ano, závisí to na implementaci. SIGSEGV je pravděpodobný výsledek dobrého kompilátoru.
Komentáře
- Jak je na tom kompilátor, který segfaults “ dobrý „? To
<
by nemělo mít žádný účinek nebo by se mělo zabalit. - Okamžité vytvoření chyby běhového modulu při porušení hranic je nejlepší, protože umožňuje programátorovi najít a opravit chybu jako co nejrychleji. Pokud necháte buggy program chvíli běžet a nahodile poškodíte paměť, než dojde k havárii, bude diagnostika problému obtížnější. Úplná prevence havárie, jak navrhujete, je nejhorší; programátor může nechat program “ pracovat “ a poté být veřejně ponížen, když dojde k chybě standardních překladačů a tlumočníků.
- Naopak, zachytit porušení pravidel před dobou běhu není obecně možné, ani zvlášť užitečné v případech, kdy je to možné. Produkce popisnější chyby za běhu by byla v pořádku, ale nechat ji operačním systémem zachytit jako segfault je skvělé, protože to ‚ nemá žádné náklady na rychlost. (V případě, že to ‚ s není jasné, kompilátor sám o sobě ‚ t segfault – produkuje spustitelné soubory, které segfault, jakmile se pokusí pro přístup k paměti mimo hranice.)
- Můžete poskytnout implementaci, která produkuje toto chování a byla vytvořena před zveřejněním této výzvy? Pokud ne, tato odpověď je neplatná.
- Kontroly hranic jsou specifické pro konkrétní implementaci, takže jsem si ‚ jistý, že by se vyskytly chyby, které by se vyskytly.Byl by nějaký SIGSEGV? Pochybuji. Existuje velké množství programů, které závisí na zalomení pole vlevo. Může být docela pohodlné mít na obou stranách rozšiřitelné úložiště.
Odpovědět
Haskell, 31
foreign import ccall main::IO()
Při kompilaci s GHC a spuštění se vytvoří segfault. Nejsou nutné žádné příznaky rozšíření, protože rozhraní cizích funkcí je ve standardu Haskell 2010.
Komentáře
- Awwww. Chtěl jsem zveřejnit
import Foreign;main=peek nullPtr::IO Int
, ale to ‚ s 40.
odpověď
Bash, 4 bajty
golf
. $0
Rekurzivně zahrnout skript do sebe.
Vysvětlení
Rekurzivní “ zdroj “ (.) operace nakonec způsobí přetečení zásobníku a protože Bash se neintegruje s libsigsegv , výsledkem je SIGSEGV.
Upozorňujeme, že se nejedná o chybu, ale o očekávané chování, jak je popsáno zde .
Test
./bang Segmentation fault (core dumped)
Odpověď
Python 33
import os os.kill(os.getpid(),11)
Odesílání signálu 11 (SIGSEGV) v pythonu.
Komentáře
- Také 33 znaků:
from os import*
akill(getpid(),11)
odpověď
C – 11 (19) 7 (15) 6 (14) 1 znaků, AT & T x86 assembler – 8 (24) znaků
Verze C je:
*(int*)0=0;
Celý program (ne tak docela ISO -kompatibilní, předpokládejme, že K & RC) je dlouhý 19 znaků:
main(){*(int*)0=0;}
Assembler varianta:
orl $0,0
Celý program má 24 znaků (pouze pro vyhodnocení, protože to není vlastně assembler):
main(){asm("orl $0,0");}
EDIT :
Několik variant C. První používá nulovou inicializaci proměnné globálního ukazatele:
*p;main(){*p=0;}
Druhý používá nekonečnou rekurzi:
main(){main();}
Poslední varianta je nejkratší – 7 (15) znaků.
EDIT 2 :
Vynalezl ještě jednu variantu, která je kratší než kterýkoli z výše uvedených – 6 (14) znaků. Předpokládá, že doslovné řetězce jsou vloženy do segmentu jen pro čtení.
main(){*""=0;}
EDIT 3 :
A můj poslední pokus – 1 znak dlouhý:
P
Stačí to takto zkompilovat :
cc -o segv -DP="main(){main();}" segv.c
Komentáře
- v jazyce C isn ‚ t main; pouze 5 znaků
- : Linker nekontroluje ‚, zda je main funkční nebo ne. Stačí jej předat zavaděč a návrat sigsegv
- @FUZxxl V tomto případě je
main
globální proměnná int s nulovou inicializací, takže to, co dostaneme, je výsledek pokusu o provedení nula bajtů. V x86 to ‚ d může být něco jakoadd %al,(%rax)
, což je naprosto platná instrukce, která se snaží dosáhnout paměti na adrese uložené v%rax
. Šance na dobrou adresu je minimální.- Poslední položku lze samozřejmě použít pro všechno, stačí zadat správné argumenty kompilátoru. Díky tomu by se měl stát automatickým vítězem jakékoli soutěže v golfu kódu. 🙂
- Příznaky jiných překladačů než ty, které zvolí jazykovou verzi, se obvykle započítávají do součtu.
- @FUZxxl V tomto případě je
Odpověď
Perl, 10/12 znaků
Mírně podvádějícím řešením je oholit jeden znak Joey Adams „bash trik :
kill 11,$$
Chcete-li však získat skutečný segfault v Perlu, je unpack p
zřejmým řešením :
unpack p,1x8
Technicky to není „zaručeno na segfault, protože adresa 0x31313131 (nebo 0x3131313131313131 na 64bitových systémech) mohl by náhodou ukázat na platný adresní prostor. Ale šance jsou proti. Pokud je perl někdy portován na platformy, kde jsou ukazatele delší než 64 bitů, bude třeba x8
zvýšit.
Komentáře
- Co je to
1x8
? - @HannesKarppila ‚ je krátký způsob psaní
"11111111".
Odpověď
dc – 7 znaků
[dx0]dx
způsobí přetečení zásobníku
Komentáře
- Jsou díla, ale můžete je rozvinout? Proč se tak chová?
-
[dx0]
ukládádx0
do zásobníku a potéd
duplikuje prvek horního zásobníku, potéx
zobrazí prvek horního zásobníku (dx0
) a provede jej. Který duplikuje prvek nejvyššího zásobníku a začne jej spouštět …0
tam musí být, aby tomu zabránil, aby se to stalo koncovým voláním, takže se všichni hromadí.
Odpověď
PicoLisp – 4 znaky
$ pil : ("0) Segmentation fault
Toto je zamýšlené chování. Jak je popsáno na jejich webových stránkách:
Pokud některé programovací jazyky tvrdí, že jsou „švýcarským armádním nožem programování“, pak se PicoLisp může nazývat „Skalpel“ of Programming „: Ostré, přesné, malé a lehké, ale také nebezpečné v rukou nezkušených.
Odpovědět
F90 – 39 bajtů
real,pointer::p(:)=>null() p(1)=0. end
Kompilace:
gfortran segv.f90 -o segv
Provedení:
./segv Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 0x7FF85FCAE777 #1 0x7FF85FCAED7E #2 0x7FF85F906D3F #3 0x40068F in MAIN__ at segv.f90:? Erreur de segmentation (core dumped)
Materiály:
gfortran --version GNU Fortran (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
Komentáře
- Hezký první příspěvek.
Odpověď
Vlastně , 17 16 11 10 9 bajtů
⌠[]+⌡9!*.
Pokud výše uvedená chyba selže, zkuste zvýšit počet (víceciferná čísla jsou uvedena ve skutečnosti s úvodním dvojtečkou )
Havaruje interpret r využitím chyby v pythonu zahrnující hluboce vnořené itertools.chain
objekty, které skutečně používají k implementaci +
operátor.
Odpověď
OCaml, 13 bajtů
Obj.magic 0 0
Používá funkci Obj.magic
, která nebezpečně vynutí všechny dva typy. V tomto případě vynucuje 0 (uloženo jako okamžitá hodnota 1, kvůli bitu značky použitému GC) na typ funkce (uložen jako ukazatel). Snaží se tedy dereferovat adresu 1, což bude samozřejmě segfault.
Komentáře
-
it coerces 0 (stored as the immediate value 1)
– proč je 0 uložena jako 1? - @Skyler viz úpravy
-
Obj.magic()0
je o jeden znak kratší 🙂
Odpověď
Pyth, 3 znaky
j1Z
To by byla část, kde vysvětlím, jak jsem přišel k této odpovědi, kromě toho, že legitimně nemám žádnou stopu . Pokud mi to někdo může vysvětlit, budu vděčný.
Tady je v online tlumočníkovi.
Vysvětlení
j
umocní základnu na druhou a rekurzivně se volá, dokud základna není alespoň tak velká jako číslo. Protože základna je 0 , nikdy se nestane. S dostatečně vysokým limitem rekurze získáte segfault.
Komentáře
- Na něco jsem přišel! Při procházení zdroje Pyth ‚ s jsem zjistil, že tento kód
j
na1
a0
, které se snaží převést1
na základní0
. Proč ta segfaults, nemám nápad … - Viz zde .
j
druhou mocninu základny a volá se rekurzivně, dokud základna není alespoň tak velká jako číslo. Protože základna je 0 , nikdy se to nestane. S dostatečně vysokým limitem rekurze získáte segfault. - @Dennis IDEone
- @SeeRhino The Pyth interpreter nastavuje limit rekurze na 100 000. Alespoň na TIO to ‚ stačí na segfault.
Odpověď
C # – 62
System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr.Zero);
C # / nebezpečné, 23 bajtů
unsafe{int i=*(int*)0;}
Z nějakého důvodu nerozumím, *(int*)0=0
jen hodí NullReferenceException, zatímco tato verze poskytuje správné narušení přístupu.
Komentáře
-
int i=*(int*)0;
vrací mi NullReferenceException. - Můžete zkusit získat přístup k negativnímu místu, například
*(int*)-1=0
a získat narušení přístupu. - Zvláštní výjimkou je právě to, co clr zabalí to do a je bezvýznamný. Samotný operační systém ve všech těchto případech ve skutečnosti způsobí chybu seg.
- Důvod, proč
*(int*)0=0
vyvolá výjimku, je pravděpodobně způsoben optimalizací. Konkrétně, aby se zabránilo nákladům na kontrolunull
, může optimalizátor odstranit nulové kontroly, ale když dojde k segfault, může to znovu vytvořit jako správnýNullReferenceException
.
Odpověď
19 znaků v C
main(a){*(&a-1)=1;}
Poškodí hodnotu návratové adresy hlavní funkce, takže po návratu main
získá SIGSEGV.
Komentáře
- Závisí to na rozvržení rámce zásobníku, takže v některé architektuře možná nemůže selhat.
- Proč ne jednoduše
main;
, nebomain(){*""=0;}
? - @Sapphire_Brick
main;
je již uveden v jiné odpovědi. - @saeedn Proč to tedy vůbec zveřejňovat? Tento není ‚ ani druhý nejkratší!
- @Sapphire_Brick V době, kdy jsem zveřejňoval svůj,
main;
nebyl ‚ t zveřejněn a já jsem ‚ nevěděl, že to funguje. Poukázal jsem jen na to, že je to již dáno a nemá smysl měnit svou odpověď. Kromě toho zde lidé ‚ nezveřejňují příspěvky jen pro nejkratší dobu, někdy je zajímavý i jiný způsob řešení problému.
Odpověď
Cython, 14
Toto se často hodí pro účely ladění.
a=(<int*>0)[0]
Odpověď
J (6)
memf 1
memf
znamená volnou paměť, 1
je interpretován jako ukazatel.
Komentáře
- Proč
1
spíše než0
? Je legální uvolnit nulový ukazatel v J?
Odpověď
Matlab – ano, je to možné!
V reakci na mou otázku přišel Amro s tímto vtipem:
S = struct(); S = setfield(S, {}, "g", {}, 0)
Komentáře
- Uveďte prosím verzi Matlabu – R2015B (a 2016B také) jen vyvolá chybu: Chyba při používání setfield (řádek 56) Alespoň jedna je vyžadován index.
- @FlorianCastellane Nyní nemůžeme vyzkoušet všechny verze, ale bylo potvrzeno, že v některých verzích, nejnovější je 2014b a nejdříve 2012a, je uveden segfault.
Odpověď
C – 14 znaků
Nezapomeňte sestavit prázdný soubor s cc -nostartfiles c.c
Vysvětlení:
Co se pokazilo, je to, že jsme s _start zacházeli, jako by to byla funkce C, a pokusil se z toho vrátit. Ve skutečnosti to není vůbec funkce. Je to jen symbol v souboru objektu, který linker používá k vyhledání vstupního bodu programu. Když je vyvolán náš program, je vyvolán přímo. Pokud bychom se měli podívat, viděli bychom, že hodnota v horní části zásobníku byla číslo 1, což je určitě velmi neadresné. Ve skutečnosti je to hodnota argc našeho programu. Poté přichází prvky pole argv, včetně zakončovacího prvku NULL, následovaného prvky envp. A to je vše. V zásobníku není žádná zpáteční adresa.
Komentáře
- I ‚ jsem si jistý, že musíte bodovat s dalšími args
- Pro speciální příznak musíte přidat 14 bajtů.
- @ErikGolfer エ リ ッ ク ゴ ル フ ァ ー -nostartfiles je ve skutečnosti 13 bajtů dlouhý 🙂
- @CharlesPaulet Myslím, že musíte počítat také prostor.
Odpovědět
Sestava Unix PDP-11, 18 bajtů binární, 7 bajtů zdroj
(to se u mě stává tématem, možná proto, že je to jediný jazyk, o kterém vím, že ne – jeden jiný zde dělá.)
inc(r0)
Zvyšuje jeden bajt adresovaný počáteční hodnotou r0 [což je podle simh debuggeru 05162] od spuštění programu.
0000000 000407 000002 000000 000000 000000 000000 000000 000000 0000020 005210 000000
A jako vždy lze cizí bajty na konci odstranit pomocí stripu.
Vytvořil jsem několik pokusy o zkrácení zdroje, ale vždy skončily ge buď syntaktická chyba, nebo SIGBUS.