Undefined Behaviour Killed My Cat [zamknięty]


82

Undefined Behavior Killed My Cat

Powszechnie wiadomo, że niezdefiniowane zachowanie może zabić twojego kota [potrzebne źródło] .
Ale czy to możliwe?

Twoje zadanie

  1. Napisz program, który wywołuje niezdefiniowane zachowanie.
  2. Opisz scenariusz, który rozpoczyna się od uruchomienia powyższego programu, w wyniku czego catis Felis kończy życie, gdy jesteś właścicielem, w wyniku wyżej wspomnianego UB.
  3. Oszacuj prawdopodobieństwo dla każdego etapu w scenariuszu.
  4. Oblicz całkowite prawdopodobieństwo, że jedno uruchomienie programu zabije twojego kota.

Zasady

  1. To , więc bądź kreatywny, jeśli możesz.
  2. Jest to wyzwanie związane z programowaniem, więc łańcuch wydarzeń powinien znajdować się głównie w komputerze, a nie w realnym świecie (oczywiście, jeśli musi dotrzeć do realnego świata, jeśli tam jest twój kot).
  3. Jeśli wybierzesz język, który nie ma niezdefiniowanego zachowania, użyj czegoś podobnego.
  4. Żadne zwierzęta nie mogą zostać skrzywdzone przy tworzeniu twojej odpowiedzi.

Punktacja

Liczba głosów plus całkowite prawdopodobieństwo scenariusza (które nie może przekroczyć 1).

Przykład w C:

main(){printf();}

Scenariusz:

  1. printfwywoływane ze śmieciami ze stosu - niezdefiniowane zachowanie. Prawdopodobieństwo: 100%.
  2. Pierwszym parametrem jest łańcuch Your cat is ugly!. Prawdopodobieństwo: (1/256) 17 = (1,148 * 10-37 )%.
  3. Widząc wiadomość, podnosisz broń i zabijasz kota. Prawdopodobieństwo: 3%.
  4. Kot umiera. Prawdopodobieństwo: 93%.

Całkowite prawdopodobieństwo: (3,202 * 10 -39 )%.


50
1) Wywołaj niezdefiniowane zachowanie 2) Pozostań zainspirowany samym faktem, że możesz wywoływać niezdefiniowane zachowanie i żyć długim, szczęśliwym życiem 3) Kot umiera ze starości. Całkowite prawdopodobieństwo: 100%
Geobits

5
@Oberon Zabiłbym siebie, gdybym nie wymyślił jednego sposobu na stworzenie UB po tak długim programowaniu. Wtedy kot nie byłby już w moim posiadaniu. Wywołanie UB utrzymuje mnie przy życiu, dzięki czemu „... w rezultacie kończę jego życie będąc w posiadaniu …”. Niejednoznaczne analizowanie FTW.
Geobits

8
Byłbym bardziej rozbawiony, gdyby ktoś zinterpretował to, aby zabić catpolecenie lub coś w tym rodzaju.
keshlam

5
-1 Kocham koty. Dlaczego koty Dlaczego nie zabić robactwa?
VX

22
Jeśli kot ma zostać zjedzony, Python jest rozwiązaniem.
Nicolas Barbulesco

Odpowiedzi:


113

do

Większość odpowiedzi na to pytanie błędnie zinterpretowała pytanie, ponieważ zabijało catproces w systemie UNIX. Oto program, który może spowodować upadek biologicznej formy życia gatunku Felis Cattus, jak określono w pytaniu.

Ten przykład działa w systemie Windows, ale można go łatwo przenieść do większości systemów operacyjnych UNIX, zastępując iexplore -kpolecenie uruchomienia zainstalowanej przeglądarki internetowej.

#include <stdlib.h>
#include <stdio.h>    

int main() {
    char i; // uninitialised
    printf("Redirecting you to a website which will inform you how to properly feed your cat.");
    if (i != 42) {
         system("iexplore -k https://pets.stackexchange.com/questions/tagged/cats+diet");
    } else {
         system("iexplore -k https://cooking.stackexchange.com/questions/tagged/chocolate");
    }
    return 0;
}

Ten program udaje, że udziela porad dotyczących diety kotów.

Uruchomi Internet Explorera i przekieruje użytkownika do stosu zwierząt domowych, wymieniając wiele przydatnych pytań na temat karmienia kotów. Istnieje jednak niska (1/256) szansa, że ​​wyśle ​​użytkownika do gotowania stosu wymiany zamiast listy wskazówek, jak przygotować dania zawierające czekoladę, która jest bardzo toksyczna dla kotów . Co gorsza, uruchomi przeglądarkę internetową w trybie kiosku (pełny ekran), który ukrywa pasek adresu i jest trudny do uniknięcia dla użytkownika nie znającego się na technologii.

Ten sprytny podstęp zmusi użytkownika do karmienia swojej kota czekoladą, wierząc, że jest to odpowiednia dieta, a tym samym niechcący ją zabije.


3
Pióro jest potężniejsze niż miecz! :)
Pieter Witvoet

12
Wygląda to na jedyne jak dotąd rozwiązanie, które ma realną szansę na zabicie kota. Jestem zmuszony głosować, choć mam szczerą nadzieję, że nikt nigdy nie zastosuje go w praktyce.
Charles Staats,

43
Internet Explorer może sam zabić twojego kota.
Michael Hampton

4
Czy możesz dodać scenariusz krok po kroku, który zabija kota, z analizą prawdopodobieństwa (jak w przykładzie)? W tej chwili nie jest to prawidłowa odpowiedź.
ugoren

3
Korzystanie z Internet Explorera wywołuje niezdefiniowane zachowanie w ME. - przepraszam, musiałem to powiedzieć.
tomsmeding

88

Grzmotnąć

Zgodnie z tym , INT_MIN % -1może, ale nie musi być niezdefiniowany (co ???) , a zatem może powodować problemy dla dowolnego języka zaimplementowanego w c / c ++.

#!/bin/bash

cat <<< $((2**63%-1))

catZostanie zabity wcześnie, jeśli rodzic bashproces ulega awarii, która może lub nie może się zdarzyć.

Na mojej maszynie wirtualnej otrzymuję ten wynik:

$ ./schroedinger.sh
./schroedinger.sh: line 3:  7805 Floating point exception(core dumped) cat <<< $((2**63/-1))
$ 

(Naprawdę nie rozumiem punktacji dla tego pytania, ale i tak tu idzie)

Oblicz $((2**63%-1)). Awaria zawsze zdarza się w wersji bash 4.2.25, ale wydaje się, że zawiesiła się na niektórych wersjach 3.x. Więcej niepewności. Mógłbym powiedzieć dokładne prawdopodobieństwo, ale z powodu zasady nieoznaczoności Heisenburga upadłbym wtedy do czarnej dziury. Lub coś. Myślę więc, że możemy spokojnie powiedzieć, że prawdopodobieństwo wynosi około 42%.


4
@ klingt.net: Nazywa się „Here Strings” - jest znacznie bardziej dostępny w Google ... to skrótecho $((-2**63/-1)) | cat
VX

14
+1 za używanie prawdziwego cat.
Alvin Wong,

1
@mardavi INT_MAX = 2^63 - 1. Jeśli dodamy 1 do INT_MAX, przestrzeń liczbowa 64-bitowa zawija się i otrzymujemy INT_MIN. Innymi słowy w podpisanym 64-bitowej liczby całkowitej arytmetyki 2^63 == -2^63. Mógłbym użyć -2**63, ale wolałem zwięzłość bez -, ponieważ arytmetyka modułowa jest w tym przypadku taka sama.
Cyfrowa trauma


1
Czy możesz dodać scenariusz krok po kroku, który zabija kota, z analizą prawdopodobieństwa (jak w przykładzie)? W tej chwili nie jest to prawidłowa odpowiedź.
ugoren

40

C (punkt sekwencji)

deadcat.c:

#include <stdio.h>
int main()
{
    int i=3;
    int k=0;
    k=i+(++i);
    if (k==7)
        printf("The cat is fine. k=i+(++i) =%d\n",k);
    else
        printf("Urgent Notice: Your cat has rabies. k=i+(++i) =%d\n",k);
}

Wykonanie (lub nie):

$ clang -w deadcat.c -o deadcat; ./deadcat
The cat is fine. k=i+(++i) =7
$ gcc deadcat.c -o deadcat; ./deadcat
Urgent Notice: Your cat has rabies. k=i+(++i) =8

Scenariusz i prawdopodobieństwo

Zakładając, że pięć procent osób korzystających z tego programu używa clang do kompilacji kodu C (w porównaniu do 90 procent przy użyciu gcc i 5 procent przy użyciu innych kompilatorów C):

Prawdopodobieństwo otrzymania „Kota jest w porządku”. = .050
 Prawdopodobieństwo otrzymania „Pilnego powiadomienia: Twój kot ma wściekliznę”. = .950

 Prawdopodobieństwo reakcji na „Twój kot ma wściekliznę” poprzez odłożenie go = 0,040
 Prawdopodobieństwo zignorowania ogłoszenia = .900
 Prawdopodobieństwo zabrania kota do weterynarza na leczenie = 0,060

 Całkowite prawdopodobieństwo życia kota: 0,05 + 0,95 * (0,90 + 0,06) = 0,962
 Całkowite prawdopodobieństwo śmierci kota: 0,95 * .04 = 0,038
 Sprawdź: Całkowite prawdopodobieństwo życia lub śmierci kota: = 1.000

Wyjaśnienie:

k = i + (++ i) uzyskuje dostęp i zmienia „i” między punktami sekwencji. Prawdopodobieństwo nie jest określane przez program; zależy to od wyboru kompilatora dokonanego przez użytkownika. „Niezdefiniowany” niekoniecznie oznacza „losowy”.

Zobacz https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points


4
+1 za demonstrację zachowania z różnymi kompilatorami.
ntoskrnl

1
poziom optymalizacji może również zmienić zachowanie
maniak zapadkowy

1
@ratchet freak: Tak, ale nie mogłem tego zademonstrować w przypadku tego konkretnego problemu. Próbowałem -O0, -O1, -O2 i -O3 na wielu wersjach gcc, od gcc-4.2.3 do gcc-4.8.2 i cc-5.0 na SunOS, ale wszystkie zabiły kota.
Glenn Randers-Pehrson

2
Czy możesz dodać scenariusz krok po kroku, który zabija kota, z analizą prawdopodobieństwa (jak w przykładzie)? W tej chwili nie jest to prawidłowa odpowiedź.
ugoren

1
Zakładałem, że wszystkie koty zabrane do weterynarza na leczenie będą żyły. Prawdopodobnie niektóre z nich umrą na skutek zarażenia chorobą kotów lub nadużyciami weterynaryjnymi. To może nieco zmienić ostateczne prawdopodobieństwo, powiedzmy .96 / .04
Glenn Randers-Pehrson

37

do

Historia

Moja żona odziedziczyła kota od rodziny. Niestety jestem bardzo uczulony na zwierzęta. Kot był już daleko od swojej świetności i powinien był zostać uśmiercony, zanim jeszcze go dostaliśmy, ale nie mogła się zmusić do pozbycia się go ze względu na jego sentymentalną wartość. I wykluły plan, aby zakończyć mój Jego cierpienia.

Jechaliśmy na dłuższy urlop, ale ona nie chciała wejść na pokład kota w gabinecie weterynarza. Martwiła się tym, że zapada na nią choroba lub jest źle traktowana. Stworzyłem automatyczny karmnik dla kotów, abyśmy mogli zostawić go w domu. Napisałem oprogramowanie mikrokontrolera w C. Zawierający plik mainwyglądał podobnie do poniższego kodu.

Jednak moja żona jest również programistą i znała moje uczucia do kota, dlatego nalegała na weryfikację kodu, zanim zgodziła się zostawić go w domu bez opieki. Miała kilka obaw, w tym:

  • main nie ma podpisu zgodnego ze standardami (dla hostowanej implementacji)
  • main nie zwraca wartości
  • tempTmjest używany niezainicjowany, ponieważ malloczostał wywołany zamiastcalloc
  • zwracana wartość mallocnie powinna być rzutowana
  • czas mikrokontrolera może być niedokładny lub przewracany (podobnie jak problemy z czasem Y2K lub Unix 2038)
  • elapsedTimezmienna może nie mieć wystarczającego zakresu

Potrzeba było wielu przekonujących, ale w końcu zgodziła się, że tezy nie były problemami z różnych powodów (nie bolało, że spóźniliśmy się już na nasz lot). Ponieważ nie było czasu na testy na żywo, zatwierdziła kod i pojechaliśmy na wakacje. Kiedy wróciliśmy kilka tygodni później, moja nędza mojego kota się skończyła (chociaż w rezultacie mam teraz dużo więcej).

† Całkowicie fikcyjny scenariusz, bez obaw.


Kod

#include <time.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

//#include "feedcat.h"
// contains extern void FeedCat(struct tm *);
// implemented in feedcat.c
// stub included here for demonstration only
#include <stdio.h>
// passed by pointer to avoid putting large structure on stack (which is very limited)
void FeedCat(struct tm *amPm)
{
    if(amPm->tm_hour >= 12)
        printf("Feeding cat dinner portion\n");
    else
        printf("Feeding cat breakfast portion\n");
}

// fallback value calculated based on MCU clock rate and average CPI
const uintmax_t FALLBACK_COUNTER_LIMIT = UINTMAX_MAX;

int main (void (*irqVector)(void))
{
    // small stack variables
    // seconds since last feed
    int elapsedTime = 0;
    // fallback fail-safe counter
    uintmax_t loopIterationsSinceFeed = 0;
    // last time cat was fed
    time_t lastFeedingTime;
    // current time
    time_t nowTime;

    // large struct on the heap
    // stores converted calendar time to help determine how much food to
    // dispense (morning vs. evening)
    struct tm * tempTm = (struct tm *)malloc(sizeof(struct tm));

    // assume the cat hasn't been fed for a long time (in case, for instance,
    // the feeder lost power), so make sure it's fed the first time through
    lastFeedingTime = (size_t)(-1);

    while(1)
    {
        // increment fallback counter to protect in case of time loss
        // or other anomaly
        loopIterationsSinceFeed++;

        // get current time, write into to nowTime 
        time(&nowTime);

        // calculate time since last feeding
        elapsedTime = (int)difftime(nowTime, lastFeedingTime);

        // get calendar time, write into tempTm since localtime uses an
        // internal static variable
        memcpy(&tempTm, localtime(&nowTime), sizeof(struct tm));

        // feed the cat if 12 hours have elapsed or if our fallback
        // counter reaches the limit
        if(  elapsedTime >= 12*60*60 || 
             loopIterationsSinceFeed >= FALLBACK_COUNTER_LIMIT)
        {
            // dispense food
            FeedCat(tempTm);

            // update last feeding time
            time(&lastFeedingTime);

            // reset fallback counter
            loopIterationsSinceFeed = 0;
        }
    }
}

Niezdefiniowane zachowanie:

Dla tych, którzy nie chcą zawracać sobie głowy znalezieniem samego UB:

W tym kodzie jest zdecydowanie zachowanie lokalne, nieokreślone i zdefiniowane w implementacji, ale wszystko powinno działać poprawnie. Problem tkwi w następujących wierszach kodu:

struct tm * tempTm //... //... memcpy(&tempTm, localtime(&nowTime), sizeof(struct tm));
memcpyzastępuje tempTMwskaźnik zamiast obiektu, na który wskazuje, niszcząc stos. To zastępuje, oprócz innych rzeczy, elapsedTimei loopIterationsSinceFeed. Oto przykładowy bieg, w którym wydrukowałem wartości:

pre-smash : elapsedTime=1394210441 loopIterationsSinceFeed=1 post-smash : elapsedTime=65 loopIterationsSinceFeed=0


Prawdopodobieństwo zabicia kota:

  • Biorąc pod uwagę ograniczone środowisko wykonywania i łańcuch kompilacji, zawsze występuje niezdefiniowane zachowanie.
  • Podobnie, niezdefiniowane zachowanie zawsze uniemożliwia karmnikowi działanie zgodnie z przeznaczeniem (a raczej pozwala mu „pracować” zgodnie z przeznaczeniem).
  • Jeśli karmnik nie działa, jest bardzo prawdopodobne, że kot umrze. To nie jest kot, który może sobie poradzić, a ja nie poprosiłem sąsiada, żeby zajrzał na niego.

Szacuję, że kot umiera z prawdopodobieństwem 0,995 .


Jest (pierwszy) &w memcpy, prawda?
Score_Under

@Score_Under Tak, pozwól mi trochę edytować odpowiedź. Bawiłem się innymi sposobami wykorzystania nieokreślonego zachowania, ale większość z nich była jeszcze bardziej oczywista.
jerry

1
+1 za zabicie kota, nie cat.
Kevin

31

grzmotnąć

Wersja klasyczna

cat & # This is your cat.
pkill -$RANDOM cat

Ma tę zaletę, że zabija wszystkie koty w swoim zasięgu.

Zauważ, że proces zostaje natychmiast zatrzymany , więc jedynym sposobem na zakończenie go pojedynczym wywołaniem pkill jest wysłanie SIGKILL (9).

W związku z tym:

p(SUCCESS) = p(RANDOM == 9) = 0.0275 %


Wersja kwantowa

schroedinger=/dev/null             # We'll need this guy.
heisenberg=/dev/urandom            # Also needed, for uncertainty principle.
cat $heisenberg > $schroedinger &  # Steal cat from Heisenberg and give it to Schrödinger.
felix=$!                           # Name cat for future references.
exec 2> $schroedinger              # Send all results to Schrödinger.
kill -SIGSTOP $felix               # Catch Felix and put him into a box.
if (($RANDOM & 1))                 # Flip a coin.
then kill $felix                   # Heads: Kill! Kill! Kill!
fi                                 # By now, Felix can be thought of as both alive and dead.
read -sn 1                         # Wait for somebody to open the box.
kill -SIGCONT $felix               # Let him open it.
if ps p $felix > $schroedinger     # Let Schrödinger check on Felix.
then echo The cat is alive.        # Hooray for tails!
else echo The cat is dead.         # At least, now we know.
fi                                 # This concludes the experiment.
kill -SIGKILL $felix               # Felix is no longer required.

Prawdopodobieństwo zabicia kota podczas eksperymentu: 50%


+1 Ale myślę, że jest to bardziej prawdopodobne. SIGINT (2), SIGQUIT (3), SIGABRT (6), SIGPIPE (13) i SIGTERM (15), przynajmniej zabijają go tutaj.
l0b0

@ l0b0: Nie, przynajmniej nie natychmiast. cat &próbuje czytać z terminala, ale nie może. Każdy z wymienionych przez ciebie sygnałów (i kilka innych) zadziała, jeśli później wyślesz SIGCONT (18). Również zgadzam się, że wisi i kończące kota będzie taka sama jak zabija go, ale przerywania nie wydaje się zadowalająca ...: P
Dennis

3
Niezdefiniowane zachowanie korzysta z funkcji języka, który został określony jako niezdefiniowany . Oznacza to, że projektanci języków celowo pozostawili zachowanie jakiegoś konstruktu syntaktycznego niezdefiniowanym, aby ułatwić implementację lub wskazać, że konstrukcja nigdy nie powinna być używana w żadnym prawidłowym programie. Niezdefiniowane zachowanie zwykle nie ma nic wspólnego z generowaniem liczb losowych i nie stosuje się tutaj nieokreślonego zachowania.
OregonTrail,

@OregonTrail: Reguły mówią, że jeśli wybierzesz język, który nie ma niezdefiniowanego zachowania, użyj czegoś podobnego. Bash nie ma nieokreślonego zachowania, więc użyłem liczb losowych.
Dennis

3
W środowisku bash istnieje wiele niezdefiniowanych zachowań, które można wykorzystać. Na przykład odpowiedź printf @DigitalTrauma Bash używa również printf systemu, który ma wiele niezdefiniowanych zachowań.
OregonTrail

17

do

Zauważ, że działa to tylko w systemie Linux.

main() {
  FILE *f = fopen("skynet", "w");
  srand(time(0));
  while(rand() != rand())
    fputc(rand()%256, f);
  fclose(f);
  system("chmod +x skynet");
  system("./skynet");
}
  1. Zapisz losowe dane do pliku i wywołaj go (100%)
  2. Losowe dane to kod źródłowy skynet (1x10 ^ -99999999999999999999999999999999999999999999999999999999999999)
  3. Kot umiera w wyniku dnia zagłady (99,999%)

Całkowite prawdopodobieństwo: 1x10 ^ -999999999999999999999999999999999999999999999999999999999999999, ok.


hmmmm, co to jest skynet?
Sarge Barszcz

20
Gdzie jest niezdefiniowane zachowanie?
ugoren


1
@ugoren Myślę, że uruchomienie pliku z losową zawartością nie jest tak naprawdę zdefiniowane.
11684

2
@ 11684, Jeśli zawartość jest kodem skynet, programiści skynet wiedzą, co robią, nie ma niezdefiniowanego zachowania.
ugoren

15

C ++

Twój kot jest martwy i żywy, dopóki nie będziesz ciekawy. Wtedy zdajesz sobie sprawę, że istnieje 0,5 prawdopodobieństwa, że ​​Twój Kot nie żyje.

#ifdef WIN32
#pragma warning(disable: 4700)
#endif
#include <random>
#include <iostream>
#include <vector>
#include <climits>
#include <memory>
class Cat
{
public:
    enum class State {DEAD, ALIVE};
    Cat()
    {
        int x; // Uninitialized Variable on Stack
        if (x % 2 == 0) // Is the Uninitialized Variable even? 50-50
        {
            m_dead = State::DEAD;

        }
        else
        {
            m_dead = State::ALIVE;
        }
    };
    operator State() //Check if your Cat is Dead / Alive
    {
        if (m_dead == State::DEAD)
        {
            delete this; //Boom Cat is dead
            std::cout<<"Your Curiosity killed your Cat"<<std::endl;
            return false;
        }
        return m_dead;
    }
private:
    State m_dead;
};

class Schrödinger
{
public:
    Schrödinger(size_t size):m_size(size)
    {
        for(size_t i = 0; i < size; i++)
        {
            cats.push_back(new Cat());
        }
    }
    ~Schrödinger()
    {
    }
    void Curiosity()
    {
        std::default_random_engine generator;
        std::uniform_int_distribution<int> distribution(0,m_size);
        if(*cats[distribution(generator)] == Cat::State::ALIVE)
        {
            std::cout<<"You Cat is alive and still kicking" <<std::endl;
        }
    }
private:
    std::vector<Cat *> cats;
    size_t m_size;
};
int main()
{
    int size;    
    std::cout<<"How Big is Your Example Space ?";
    std::cin>>size;
    Schrödinger your(size);
    your.Curiosity();
    return 0;

}

czy możesz uzyskać dostęp this->m_deadpo delete this?
Bryan Chen,

@BryanChen: Brakowało zwrotu. Dziękuję za zwrócenie na to uwagi :-)
Abhijit

önie wydaje się być poprawnym symbolem w C ++. Może zastąp to oe.
Ruslan

13

do

Działa w systemie Linux.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void f(char x) {
    if(sleep(1)==x) system("killall cat");
}
int main() {
    char x; // uninitialised
    system("cat /dev/urandom &");
    f(x);
    return 0;
}

Prawdopodobieństwo zabicia kota: 1/256 ( sleep(1)Zwraca 0, więc zostanie zabity, jeśli xwynosi zero).

Jako bonus, zabija wszystkie koty aktualnie uruchomione w twoim systemie.


Jeśli tak bardzo nienawidzisz kotów, przedstawiam ci:

Stonoga kota (Bash)

echo "Hello World"|cat|cat|cat

Opierając się na fakcie, że w Ludzkiej stonodze (pierwsza sekwencja) wszystkie trzy psy stonogi psiej zmarły, a dwie z trzech osób ludzkiej stonogi umarły, szacuję, że prawdopodobieństwo zabicia jednego kota wynosi 5/6.


Cat Centipede jest naprawdę zabawny
Sarge Borsch

Stonoga kota powinna być „faktyczną” odpowiedzią.
Ismael Miguel

@ Ismael Miguel Prawdopodobnie masz rację, usunąłem kod C. Początkowo miał to być żart, ale później zdałem sobie sprawę, że mogę go sformułować, aby była to prawdziwa odpowiedź.
ace_HongKongIndependence

Możesz zachować swój kod C, nie mam nic przeciwko temu. Po prostu pomyślałem, że wersja bash jest bardziej odpowiednia jako odpowiedź.
Ismael Miguel

@ Ismael Miguel Nah, ten kod C i tak był dość głupi
ace_HongKongIndependence

9

JavaScript

~"cat".localeCompare("dead")
  ? "Cat is dead"
  : "Cat is fine"

Wykonanie:

  • Chrome: Wyniki w"Cat is fine"
  • Firefox: Wyniki w"Cat is dead"

Wyjaśnienie:

15.5.4.9 String.prototype.localeCompare (that)

Oba łańcuchy są porównywane w realizacji zdefiniowane mody

Cytując Glenna Randersa-Pehrsona, program nie określa prawdopodobieństwa; zależy to od wyboru przeglądarki dokonanej przez użytkownika.


Niepowtarzalne na FF 27. Na jakiej wersji testujesz?
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨dd

-1: niezdefiniowane zachowanie i zachowanie zdefiniowane w implementacji są całkowicie różne.
whitequark

2
@whitequark Nie, nie są. Jest to zdefiniowana funkcja o nieokreślonym wyniku. Ergo niezdefiniowane zachowanie.
George Reith,

1
@whitequark Nie widzę tu C. Jeśli chodzi o JavaScript Czy JavaScript ma nieokreślone zachowanie wydaje się sądzić, że zachowanie zdefiniowane w implementacji jest możliwe do przyjęcia.
George Reith,

1
@whitequark nikt inny nie jest zdezorientowany. Słowo to słowo, nie potrzebuję komitetu, który powiedziałby mi, co to znaczy.
George Reith,

9
int foo() {}

void main() {
    int x = foo();
}

Odczyt wartości funkcji, która ma zwrócić wartość, powoduje niezdefiniowane zachowanie. Teraz jest oczywiste [potrzebne źródło], że „za każdym razem, gdy osiągasz niezdefiniowane zachowanie, Bóg zabija kotka”. Korzystając z tego, dochodzimy do:

  • Prawdopodobieństwo osiągnięcia niezdefiniowanego zachowania - 100%
  • Prawdopodobnie to twój kotek zabił Bóg - 1/200 000 000, zobacz dlaczego
  • Więc prawdopodobieństwo wynosi 0,0000005%

Można go łatwo rozszerzyć za pomocą pętli, aby eksterminować wszystkie koty na świecie.


5
Twoje prawdopodobieństwo jest 100 razy za wysokie (200 milionów kotów, a nie 2 milionów).
ugoren

Mam procent. :)
Petr

1
Jest wyrażony w procentach i wciąż jest 100 razy za wysoki.
ugoren

Masz rację, najwyraźniej nie mogę już czytać liczb.
Petr

To jest niepoprawne. UB jest wywoływane tylko wtedy, gdy dzwoniący spróbuje użyć wartości zwracanej. W przeciwnym razie całkowicie legalne i dobrze zdefiniowane jest odejście od końca funkcji z typem powrotu nieważnym.
R ..

5

Java (odśmiecanie)

Chociaż kod może wywoływać System.gc (), nie zapewnia, że ​​Garbage Collector zbierze wszystkie nieużywane obiekty. Dlatego w przypadku poniższego kodu nieprzewidywalne jest, czy kot zostanie zabity, czy nie.

public class KillTheCat {
    public static void main(String[] args) throws InterruptedException {
        KillTheCat cat = new KillTheCat();
        cat = null;
        System.gc();
        System.out.println("Cat is still alive.");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Cat has been killed.");
        System.exit(0);
    }
}

Prawdopodobieństwa nie można obliczyć.

Zauważ, że wciąż istnieje szansa, że ​​kot zostanie „wskrzeszony”, jeśli w sysout i przed System.exit (0) istnieje przełącznik kontekstu w wątku GC, ale wolałem nie zakrywać go, aby uprościć koncepcję.


1
To nie jest dobre. Ten napisany kod prawie zawsze wydrukuje oba. Lepiej byłoby dodać System.out.close()po System.out.println("Cat is still alive.");linii.
durron597

O ile rozumiem, „prawie zawsze” odpowiada nieprzewidywalnemu aspektowi pytania.
user3001267

5

Czy ktoś pomyślał o zabiciu (a) cat?

[ $[ $RANDOM % 6 ] == 0 ] && rm /bin/cat || echo Meow

Prawdopodobieństwo catśmierci

Dla prawdopodobieństwa ... Myślę, że musimy rozróżnić niektóre przypadki:

  1. Użytkownik systemu Windows : Prawdopodobnie nie będzie w stanie go wykonać. Szansa na śmierć catjest bardzo niska, można bezpiecznie założyć, że wynosi zero. Jeśli ma zainstalowany Cygwin, będzie się liczyć jako użytkownik unix.
  2. Użytkownik uniksowy, działający bez uprawnień roota : Zabicie catnie powiedzie się.
  3. Użytkownik uniksowy, działający z uprawnieniami roota : Podczas gdy każde wywołanie zabije cats tylko z szansą 1/6, najprawdopodobniej powtórzy je, dopóki nie wydarzy się coś nieoczekiwanego. Zakładam, że bez utraty ogólności na catpewno umrze.

Ogólne prawdopodobieństwo zależy od sposobu mieszania użytkowników i jest trudne do ustalenia. Ale z pewnością możemy powiedzieć: Windows to bezpieczne miejsce dla kociąt.

Testowanie posłuszeństwa zasad

Żadne zwierzęta nie mogą zostać skrzywdzone przy tworzeniu twojej odpowiedzi.

To nie zabijało zwierząt, odpowiedź jest zatwierdzona przez American Humane Association .

$ file `which cat`
/bin/cat: Mach-O 64-bit executable x86_64

wyraźnie dowodzi, że catnie jest to zwierzę (o ile filenie zna żadnego dziedziczenia typu ukrytego pliku).


5

do

Jeśli imię twojego kota jest za długie, umiera. getspowoduje śmierć kota i inne problemy.

#include <stdio.h>
#include <stdbool.h>

/* Stores instances of cats. */
struct cat {
    /* 6 bytes are more than enough. */
    char name[6];

    /* Stores whether your cat is dead. */
    bool dead;
};

int main(void) {
    /* This is your cat. */
    struct cat your_cat;
    /* It lives. */
    your_cat.dead = false;
    /* Determine its name. */
    printf("Your cat name: ");
    gets(your_cat.name);

    /* Output the cat state. */
    const char *state = your_cat.dead ? "dead" : "alive";
    printf("Your cat, %s, is %s.\n", your_cat.name, state);

    return your_cat.dead;
}

4

Haskell

import Acme.Missiles
import System.IO.Unsafe
main = print (unsafePerformIO launchMissiles, undefined)

Tutaj stosujemy się unsafePerformIOdo działania, które ma obserwowalne skutki uboczne . Jest to zawsze niezdefiniowane zachowanie, a przynajmniej kolejność efektów. Więc albo program po raz pierwszy zawiesi się przy próbie oceny undefined(to, jak na ironię, nie jest niezdefiniowanym zachowaniem: nigdy nie może dać wartości, która pozwoliłaby programowi na kontynuowanie czegoś innego), lub w rzeczywistości poniesie poważną międzynarodową skutki uboczne. W takim przypadku szansa na przeżycie wynosi tylko 0,001% .

Prawdopodobieństwo zabicia kota w ten sposób: 49,9995%.


3

Czw

Ponieważ pytanie dopuszcza język, który nie ma nieokreślonego zachowania, dopóki efekt jest podobny, wybrałem Thue ze względu na jego niedeterminizm w wyborze, która reguła ma zostać wykonana, gdy istnieje więcej niż 1 reguła, którą można zastosować do bieżącego stan.

Program zostanie podany do sterownika kuchenki mikrofalowej, w której znajduje się mój kot. Drzwi do kuchenki mikrofalowej są zamknięte i wzmocnione suwakiem. Wynik programu zadecyduje, czy kuchenka mikrofalowa zacznie mikrofalować kota, czy nie.

  • Jeśli wartość wyjściowa wynosi 0, rozpoczniemy eksperyment na wpływie długiej ekspozycji mikrofal na żywego ssaka (który obecnie nie jest wystarczająco zbadany).
  • Jeśli wynik wynosi 1, będziemy zadowoleni z faktu, że kot właśnie stracił jedno ze swoich 9 żyć i wypuścił je.

i::=~0
i::=~1
::=
i

Prawdopodobieństwo zabicia kota zależy od implementacji interpretera, ale powiedzmy, że jest to 50%. Zatem prawdopodobieństwo śmierci kota wynosi 0,5 .



@Score_Under: O co ci chodzi?
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨dd

Pytanie dotyczy nieokreślonego zachowania, które polega na wykorzystaniu zachowania języka, który będzie się kompilował i działał, ale nie ma specyfikacji co do tego, co powinien zrobić. Na Math.random()przykład uzależnianie się od rzeczy nie jest zachowaniem nieokreślonym, tylko zachowaniem nieprzewidywalnym.
Score_Under

1
@Score_Under: W pytaniu3. If you choose a language that doesn't have undefined behavior, use something similar.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1

Jawa

Według specyfikacji java.util.Date zachowanie będzie niezdefiniowane. Spróbuj szczęścia:

import java.util.Date;

public class App3
{
    public static void main (String args[])
    {
        String aliveOrDead;
        Date d = new Date(-1000,-1000,-1000);
        aliveOrDead = (d.getTime()<0)? "dead" : "alive";
        System.out.println("The cat is:" +aliveOrDead );
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.