86
\$\begingroup\$

Undefined Behavior Killed My Cat

It's well known that undefined behavior can kill your cat [citation needed].
But can it?

Your Task

  1. Write a program that invokes undefined behavior.
  2. Describe a scenario that starts with the above program being run, resulting in a Felis catus ending its life while in your ownership, as a result of the aforementioned UB.
  3. Estimate the probability for each stage in the scenario.
  4. Calculate the total probability that a single run of the program would kill your cat.

Rules

  1. This is a , so be creative if you can.
  2. This is a programming related challenge, so the chain of events should be mostly within the computer, not in the real world (of course, if has to reach the real world if that's where your cat is).
  3. If you choose a language that doesn't have undefined behavior, use something similar.
  4. No animals may be harmed in the production of your answer.

Scoring

Vote count plus the scenario's total probability (which can't exceed 1).

Example in C:

main(){printf();}

Scenario:

  1. printf called with garbage from the stack - undefined behavior. Probablity: 100%.
  2. The first parameter happens to be the string Your cat is ugly!. Probablity: (1/256)17 = (1.148 * 10-37)%.
  3. Seeing the message, you pick up your gun and shoot your cat. Probability: 3%.
  4. The cat dies. Probability: 93%.

Total probability: (3.202 * 10-39)%.

\$\endgroup\$
26
  • 53
    \$\begingroup\$ 1) Invoke undefined behavior 2) Remain inspired by the mere fact that you could invoke undefined behavior, and live a long, happy life 3) Cat dies of old age. Total probability: 100% \$\endgroup\$
    – Geobits
    Mar 4, 2014 at 18:14
  • 5
    \$\begingroup\$ @Oberon I'd kill myself if I couldn't come up with a single way to create an UB after programming for so long. Then the cat would no longer be in my possession. Invoking the UB keeps me alive, so that "... ending its life while in your ownership , as a result...". Ambiguous parsing FTW. \$\endgroup\$
    – Geobits
    Mar 4, 2014 at 18:28
  • 9
    \$\begingroup\$ I'd be more amused if someone reinterprets this to kill the cat command or something of that sort. \$\endgroup\$
    – keshlam
    Mar 5, 2014 at 0:24
  • 5
    \$\begingroup\$ -1 I love cats. Why cats? Why not killinig vermin? \$\endgroup\$
    – V-X
    Mar 5, 2014 at 9:37
  • 23
    \$\begingroup\$ If a cat is to be eaten, Python is a solution. \$\endgroup\$ Mar 7, 2014 at 9:09

16 Answers 16

117
\$\begingroup\$

C

Most answers to this question misinterpreted the question in that it was killing the cat process on a UNIX system. Here is a program which can cause the demise of a biological lifeform of the species Felis Cattus as specificed by the question.

This example runs on Windows, but it could be easily ported to most UNIX operating systems by replacing iexplore -k with the command to launch an installed web browser.

#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;
}

This program pretends to provide advise about cat diet to the user.

It will start Internet Explorer and direct the user to pets stackexchange listing lots of helpful questions about how to feed cats. There is, however, a low (1/256) chance that it will send the user to cooking stackexchange instead listing tips how to prepare dishes containing chocolate, which is highly toxic to cats. To make matters worse, it will launch internet explorer in kiosk mode (fullscreen), which hides the address bar and is hard to escape from for a non-tech-savy user.

This clever ruse will coax the user into feeding their cat chocolate believing that it is an appropriate diet for it, thus causing them to inadvertedly kill it.

\$\endgroup\$
15
  • 3
    \$\begingroup\$ The pen is mightier than the sword! :) \$\endgroup\$ Mar 5, 2014 at 8:46
  • 13
    \$\begingroup\$ This looks like the only solution so far that has any realistic chance of actually killing a cat. I am forced to upvote, although I sincerely hope no one ever actually puts it into practice. \$\endgroup\$ Mar 5, 2014 at 15:45
  • 46
    \$\begingroup\$ Internet Explorer might kill your cat all by itself. \$\endgroup\$ Mar 5, 2014 at 20:35
  • 4
    \$\begingroup\$ Can you add the scenario, step by step, that kills the cat, with the probability analysis (as in the example)? As it is, this isn't a valid answer. \$\endgroup\$
    – ugoren
    Mar 6, 2014 at 19:41
  • 4
    \$\begingroup\$ Using Internet Explorer induces undefined behaviour in ME. — sorry, had to say that. \$\endgroup\$
    – tomsmeding
    Mar 23, 2014 at 21:42
89
\$\begingroup\$

Bash

According to this, INT_MIN % -1 may or may not be undefined (what ???), and so might cause trouble for any language implemented in c/c++.

#!/bin/bash

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

The cat will be killed early if the parent bash process crashes, which may or may not happen.

On my VM I get this output:

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

(I don't really understand the scoring for this question, but here goes anyway)

Calculate $((2**63%-1)). Crash always happens on bash 4.2.25, but seems to just hang on some 3.x versions. More uncertainty. I could tell you the exact probability, but due to the Heisenburg uncertainty principle I would then fall down a black hole. Or something. So I think we can safely say they probability is approximately 42%.

\$\endgroup\$
18
  • 4
    \$\begingroup\$ @klingt.net: It is called "Here Strings" - it is much more googlable... it is shortcut for echo $((-2**63/-1)) | cat \$\endgroup\$
    – V-X
    Mar 5, 2014 at 9:18
  • 14
    \$\begingroup\$ +1 for using real cat. \$\endgroup\$
    – Alvin Wong
    Mar 5, 2014 at 15:01
  • 1
    \$\begingroup\$ @mardavi INT_MAX = 2^63 - 1. If we add 1 to INT_MAX, the 64bit number space wraps around and we get INT_MIN. In other words in signed 64bit integer arithmetic, 2^63 == -2^63. I could have used -2**63, but preferred the terseness without the -, since the modular arithmetic is the same in this case. \$\endgroup\$ Mar 5, 2014 at 17:28
  • 1
    \$\begingroup\$ bugzilla.redhat.com/show_bug.cgi?id=579622 \$\endgroup\$ Mar 6, 2014 at 4:11
  • 1
    \$\begingroup\$ Can you add the scenario, step by step, that kills the cat, with the probability analysis (as in the example)? As it is, this isn't a valid answer. \$\endgroup\$
    – ugoren
    Mar 6, 2014 at 19:41
41
\$\begingroup\$

C (sequence point)

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);
}

Execution (or not):

$ 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

Scenario and probability

Assuming that five percent of people running this program use clang for compiling C code (versus 90 percent using gcc and 5 percent using other C compilers):

 Probability of getting "The cat is fine."                           =  .050
 Probability of getting "Urgent Notice: Your cat has rabies."        =  .950

 Probability of reacting to "Your cat has rabies" by putting it down =  .040
 Probability of ignoring the notice                                  =  .900
 Probability of taking the cat to the vet for treatment              =  .060

 Total probability of cat living:.05 + .95 * (.90 + .06)             =  .962
 Total probability of cat dying: .95 * .04                           =  .038
 Check: Total probability of cat living or dying:                    = 1.000

Explanation:

k=i+(++i) accesses and changes "i" between sequence points. The probability is not determinable by the program; it depends upon the choice of compiler, which is made by the user. "Undefined" does not necessarily mean "random".

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

\$\endgroup\$
9
  • 4
    \$\begingroup\$ +1 for demonstrating the behavior with different compilers. \$\endgroup\$
    – ntoskrnl
    Mar 4, 2014 at 22:33
  • 1
    \$\begingroup\$ optimization level may also change the behavior \$\endgroup\$ Mar 5, 2014 at 9:00
  • 1
    \$\begingroup\$ @ratchet freak: Yes, but I couldn't demonstrate that with this particular problem. I tried -O0,-O1,-O2, and -O3 on a number of gcc versions ranging from gcc-4.2.3 to gcc-4.8.2, and cc-5.0 on SunOS, but all of those killed the cat. \$\endgroup\$ Mar 5, 2014 at 16:18
  • 2
    \$\begingroup\$ Can you add the scenario, step by step, that kills the cat, with the probability analysis (as in the example)? As it is, this isn't a valid answer. \$\endgroup\$
    – ugoren
    Mar 6, 2014 at 19:42
  • 1
    \$\begingroup\$ I assumed that all the cats that were taken to the vet for treatment would live. Probably some of those will die from catching a communicable feline disease or from veterinary malpractice. That might change the final probabilities a little, to say .96/.04 \$\endgroup\$ Mar 6, 2014 at 21:17
39
\$\begingroup\$

C

Backstory

My wife inherited a cat from family. Unfortunately, I am very allergic to animals. The cat was well past its prime and should have been euthanized even before we got it, but she could not bring herself to get rid of it due to its sentimental value. I hatched a plan to end my its suffering.

We were going on an extended vacation, but she did not want to board the cat at the veterinarian's office. She was concerned about it contracting illness or being mistreated. I created an automatic cat feeder so that we could leave it at home. I wrote the microcontroller's firmware in C. The file containing main looked similar to the code below.

However, my wife is also a programmer and knew my feelings towards the cat, so she insisted on a code-review before agreeing to leave it at home unattended. She had several concerns, including:

  • main does not have a standards compliant signature (for a hosted implementation)
  • main does not return a value
  • tempTm is used uninitialized since malloc was called instead of calloc
  • the return value of malloc should not be cast
  • the microcontroller time may be inaccurate or roll over (similar to the Y2K or Unix time 2038 problems)
  • the elapsedTime variable may not have sufficient range

It took a lot of convincing, but she finally agreed that theses weren't problems for various reasons (it didn't hurt that we were already late for our flight). Since there was no time for live testing, she approved the code and we went on vacation. When we returned a few weeks later, my the cat's misery was over (though as a result I've now got plenty more).

† Entirely fictitious scenario, no worries.


Code

#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;
        }
    }
}

Undefined behavior:

For those who don't want to bother finding the UB themselves:

There's definitely local-specific, unspecified, and implementation-defined behavior in this code, but that all should work correctly. The problem is in the following lines of code:

struct tm * tempTm //... //... memcpy(&tempTm, localtime(&nowTime), sizeof(struct tm));
memcpy overwrites the tempTM pointer instead of the object it points to, smashing the stack. This overwrites, in addition to other things, elapsedTime and loopIterationsSinceFeed. Here's an example run where I printed out the values:

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


Probability of killing the cat:

  • Given the constrained execution environment and build chain, the undefined behavior always occurs.
  • Similarly, the undefined behavior always prevents the cat feeder from working as intended (or rather, allows it to "work" as intended).
  • If the feeder does not work, it is extremely likely the cat will die. This is not a cat that can fend for itself, and I failed to ask the neighbor to look in on it.

I estimate that the cat dies with probability 0.995.

\$\endgroup\$
3
  • \$\begingroup\$ It's the (first) & in the memcpy, right? \$\endgroup\$ Mar 7, 2014 at 2:39
  • \$\begingroup\$ @Score_Under Yes, let me edit the answer a little. I played around with other ways to harness undefined behavior, but most were even more obvious. \$\endgroup\$
    – jerry
    Mar 7, 2014 at 16:03
  • 3
    \$\begingroup\$ +1 for killing a cat, not cat. \$\endgroup\$
    – Kevin
    Mar 23, 2014 at 18:10
33
\$\begingroup\$

bash

Classic version

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

Has the advantage of killing all cats in its range.

Note that the process is stopped immediately, so the only way to end it with a single invocation of pkill is to send SIGKILL (9).

Therefore:

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


Quantum version

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.

Probability of killing the cat during the experiment: 50 %

\$\endgroup\$
6
  • \$\begingroup\$ +1 But it's rather more likely than that I think. SIGINT (2), SIGQUIT (3), SIGABRT (6), SIGPIPE (13) and SIGTERM (15), at least, kills it here. \$\endgroup\$
    – l0b0
    Mar 5, 2014 at 9:27
  • \$\begingroup\$ @l0b0: It doesn't, at least not immediately. cat & attempts to read from the terminal, but can't. Any of the signals you mentioned (and a few more) will work if you send SIGCONT (18) afterwards. Also, I agree that hanging up and terminating the cat would be the same as killing it, but interrupting it doesn't seem satisfactory... :P \$\endgroup\$
    – Dennis
    Mar 5, 2014 at 12:22
  • 3
    \$\begingroup\$ Undefined behavior is using a feature of a language that has been specified as undefined. That is, the language designers have purposefully left the behavior of some syntactical construct undefined in order to make implementation easier, or to indicate that the construct should never be used in any valid program. Undefined behavior usually has nothing to do with random number generation, and there is no undefined behavior being used here. \$\endgroup\$ Mar 5, 2014 at 15:38
  • \$\begingroup\$ @OregonTrail: The rules say If you choose a language that doesn't have undefined behavior, use something similar. Bash doesn't have undefined behavior, so I used random numbers. \$\endgroup\$
    – Dennis
    Mar 5, 2014 at 15:43
  • 3
    \$\begingroup\$ There's plenty of undefined behavior in bash's environment which can be used. For example, the answer by @DigitalTrauma Bash's printf also uses the system's printf which has plenty of undefined behavior. \$\endgroup\$ Mar 5, 2014 at 15:50
17
\$\begingroup\$

C

Note that this only works on 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. Write random data to a file and invoke it (100%)
  2. Random data happens to be the source code to skynet (1x10^-999999999999999999999999999999999999999999999999999999999999999, aprox.)
  3. Cat dies in resulting doomsday (99.999%)

Total probability: 1x10^-999999999999999999999999999999999999999999999999999999999999999, aprox.

\$\endgroup\$
6
  • \$\begingroup\$ hmmmm, what is skynet? \$\endgroup\$ Mar 4, 2014 at 22:20
  • 21
    \$\begingroup\$ Where's the undefined behavior? \$\endgroup\$
    – ugoren
    Mar 4, 2014 at 23:45
  • \$\begingroup\$ @SargeBorsch: en.wikipedia.org/wiki/Skynet_(Terminator) \$\endgroup\$
    – cHao
    Mar 6, 2014 at 4:23
  • 1
    \$\begingroup\$ @ugoren I think running a file with random contents isn't really defined. \$\endgroup\$
    – 11684
    Mar 6, 2014 at 8:33
  • 3
    \$\begingroup\$ @11684, If the contents happen to be the code to skynet, an skynet's programmers know what they're doing, there's no undefined behavior. \$\endgroup\$
    – ugoren
    Mar 6, 2014 at 15:29
16
\$\begingroup\$

C++

Your Cat is Both Dead and Alive until you are Curious. Then you realize that there is a 0.5 probability that your Cat is Dead.

#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;

}
\$\endgroup\$
3
  • \$\begingroup\$ can you access this->m_dead after delete this? \$\endgroup\$
    – Bryan Chen
    Mar 5, 2014 at 1:37
  • \$\begingroup\$ @BryanChen: A return was missing. THank you for pointing it out :-) \$\endgroup\$
    – Abhijit
    Mar 5, 2014 at 5:32
  • \$\begingroup\$ ö doesn't seem to be a valid symbol in C++. Maybe replace it with oe. \$\endgroup\$
    – Ruslan
    Mar 6, 2014 at 10:25
13
\$\begingroup\$

C

Runs on 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;
}

Probability of killing the cat: 1/256 (The sleep(1) returns 0, so it will be killed if x is zero.)

As a bonus, it kills all cats currently running on your system.


If you hate cats so much, I present to you:

The Cat Centipede (Bash)

echo "Hello World"|cat|cat|cat

Based on the fact that, in The Human Centipede (First Sequence), all three dogs of the dog centipede died, and two out of three people of the human centipede died, I estimate that the probability of killing one cat is 5/6.

\$\endgroup\$
6
  • \$\begingroup\$ Cat Centipede is truly funny \$\endgroup\$ Mar 4, 2014 at 22:21
  • \$\begingroup\$ The cat centipede should be the "actual" answer. \$\endgroup\$ Mar 4, 2014 at 23:06
  • \$\begingroup\$ @Ismael Miguel You're probably right, I've removed the C code. At first it was meant to be a joke, but later I realised that I could rephrase it to make it an actual answer. \$\endgroup\$
    – user12205
    Mar 4, 2014 at 23:21
  • \$\begingroup\$ You can keep your C code, I have and had nothing against it. I just though that the bash version was more suitable as an answer. \$\endgroup\$ Mar 4, 2014 at 23:45
  • \$\begingroup\$ @Ismael Miguel Nah, that C code was quite stupid anyway \$\endgroup\$
    – user12205
    Mar 4, 2014 at 23:48
10
\$\begingroup\$

JavaScript

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

Execution:

  • Chrome: Results in "Cat is fine"
  • Firefox: Results in "Cat is dead"

Explanation:

15.5.4.9 String.prototype.localeCompare (that)

The two Strings are compared in an implementation-defined fashion

Quoting Glenn Randers-Pehrson, the probability is not determinable by the program; it depends upon the choice of browser, which is made by the user.

\$\endgroup\$
8
  • \$\begingroup\$ Not reproducible on FF 27. Which version are you testing on? \$\endgroup\$ Mar 5, 2014 at 19:09
  • \$\begingroup\$ -1: undefined behavior and implementation-defined behavior are completely different. \$\endgroup\$
    – Catherine
    Mar 5, 2014 at 22:26
  • 3
    \$\begingroup\$ @whitequark No they aren't. It is a defined function with an undefined outcome. Ergo undefined behavior. \$\endgroup\$ Mar 7, 2014 at 10:38
  • 1
    \$\begingroup\$ @whitequark I don't see any C here. As far as JavaScript is concerned Does JavaScript have undefined behaviour seems to think that implementation defined behaviour is passable. \$\endgroup\$ Mar 8, 2014 at 12:03
  • 1
    \$\begingroup\$ @whitequark nobody else is confused. A word is a word, I don't need a committee to tell me what it means. \$\endgroup\$ Mar 9, 2014 at 13:04
10
\$\begingroup\$
int foo() {}

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

Reading a value of function supposed to return a value results in undefined behaviour. Now, it is obvious,[citation needed] that "Every time you reach undefined behaviour, God kills a kitty." Using this we conclude:

  • Probability you reach undefined behaviour - 100%
  • Probability it is your kitty which god killed - 1/200 000 000 see why
  • So probability is 0.0000005%

Can be easily extended by loop to exterminate all cats in the world.

\$\endgroup\$
9
  • 5
    \$\begingroup\$ Your probability is 100 times too high (200M cats, not 2M). \$\endgroup\$
    – ugoren
    Mar 4, 2014 at 23:43
  • \$\begingroup\$ I have in in percents. :) \$\endgroup\$
    – Petr
    Mar 4, 2014 at 23:50
  • 1
    \$\begingroup\$ It's in percents, and still it's 100 times too high. \$\endgroup\$
    – ugoren
    Mar 5, 2014 at 2:36
  • \$\begingroup\$ You are right, I cannot read numbers anymore, apparently. \$\endgroup\$
    – Petr
    Mar 5, 2014 at 11:44
  • \$\begingroup\$ This is incorrect. UB is only invoked if the caller attempts to use the return value. Otherwise it is completely legal and well-defined to walk off the end of a function with non-void return type. \$\endgroup\$ Mar 6, 2014 at 20:14
6
\$\begingroup\$

Java (Garbage Collection)

Although code can invoke System.gc() is does not make sure that the Garbage Collector will collect all of the unused objects. Thus, for the following code, it's unpredictable if the cat will be killed or not.

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);
    }
}

The probability cannot be calculated.

Note that there's still a chance that the cat will be "revived" if there's a context switch in the GC thread after sysout and before System.exit(0) but I preferred not to cover it to keep the concept simpler.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ This is no good. This code as written will nearly always print both. Better would be to add System.out.close() after the System.out.println("Cat is still alive."); line. \$\endgroup\$
    – durron597
    Mar 5, 2014 at 13:19
  • \$\begingroup\$ As far as I understand, "nearly always" matches the unpredictability aspect of the question. \$\endgroup\$ Jun 8, 2016 at 0:40
6
\$\begingroup\$

C

If your cat's name is too long, it dies. gets causes cat deaths, along with other problems.

#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;
}
\$\endgroup\$
5
\$\begingroup\$

Anybody having thought of really killing (a) cat?

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

Probabilitiy of cat dying

For the probability... I guess we need to distinguish some cases:

  1. Windows user: Probably will not be able to execute it. Chance of dying cats is very low, can safely be assumed to be zero. If he's got Cygwin installed, he'll count as unix user.
  2. Unix user, running without root privileges: Killing the cat will fail.
  3. Unix user, running with root privileges: While each call will only kill cats with a chance of 1/6, he will very probably repeat it until something unexpected occurs. Without loss of generality, I assume cat will definitely die.

Overall probability depends on how the users are mixed and is hard to determine. But we can surely say: Windows is a safe place for kittens.

Testing for obedience of the rules

No animals may be harmed in the production of your answer.

This did not kill animals, the answer is approved by the American Humane Association.

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

clearly proves that cat is no animal (as long file does not know any kind of hidden file type inheritance).

\$\endgroup\$
5
\$\begingroup\$

Haskell

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

Here, we apply unsafePerformIO to an action that has observable side-effects. That is always undefined behaviour, at least so is the order of effects. So either will the program first crash on trying to evaluate undefined (that one, ironically, is not undefined behaviour: it must never yield a value that would allow the program to carry on with something else), or it will in fact incur the serious international side-effects. In that case, survival chance is only 0.001%.

Probability of killing the cat thus: 49.9995%.

\$\endgroup\$
4
\$\begingroup\$

Thue

Since the question allows for a language that doesn't have undefined behavior as long as the effect is similar, I choose Thue for its non-determinism in choosing which rule to execute when there are more than 1 rule which can be applied on the current state.

The program will be fed into the controller for a microwave oven, inside of which is my cat. The door to the microwave oven is closed and reinforced by a zip tie. The output of the program will decide whether the microwave oven starts to microwave the cat or not.

  • If the output is 0, we will start the experiment on the effect of long exposure of microwave on live mammal (which is currently insufficiently researched).
  • If the output is 1, we will just be satisfied with the fact that the cat has just lost one of its 9 lives and let it out.

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

The probability of killing the cat is dependent on the implementation of the interpreter, but let's say it's 50%. Then the probability that the cat will die is 0.5.

\$\endgroup\$
4
  • \$\begingroup\$ Non-determinate does not mean non-defined \$\endgroup\$ Mar 7, 2014 at 2:52
  • \$\begingroup\$ @Score_Under: What is your point? \$\endgroup\$ Mar 7, 2014 at 2:52
  • \$\begingroup\$ The question asks for undefined behaviour, which involves leveraging behaviour of a language which will compile and run, but has no specification as to what it should actually do. Hinging things on Math.random() for example is not undefined behaviour, just unpredictable behaviour. \$\endgroup\$ Mar 8, 2014 at 13:30
  • 1
    \$\begingroup\$ @Score_Under: In the question 3. If you choose a language that doesn't have undefined behavior, use something similar. \$\endgroup\$ Mar 8, 2014 at 14:08
1
\$\begingroup\$

Java

According to spec java.util.Date will have undefined behaviour. So try your luck:

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 );
    }
}
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.