C ++ 프로그램을 중단시키는 가장 쉬운 방법은 무엇입니까?


318

다른 충돌 프로세스와 인터페이스하는 Python 프로그램을 만들려고합니다 (내 손에서 벗어났습니다). 불행히도 내가 인터페이스하고있는 프로그램은 안정적으로 충돌하지 않습니다! 그래서 의도적으로 충돌하는 빠른 C ++ 프로그램을 만들고 싶지만 실제로 가장 좋은 방법과 가장 짧은 방법은 알지 못합니다.

int main() {
    crashyCodeGoesHere();
}

내 C ++ 프로그램이 안정적으로 충돌하도록


4
인라인 어셈블리를 사용하여 권한있는 명령을 실행할 수 있습니다.asm { cli; };
Nate Koppenhaver

@ aitchnyu 각 질문에 대한 답변의 유용성에 차이가 있다고 생각합니다. (FYI : 두 질문에 대해 아무 것도 투표하지 않았습니다)
Andrew Barber

하나가 이미 전파하는 동안 예외를 던지는 것에 대한 의견? plz chk anc 코멘트 아래 내 답변
Abhinav

4
Redis는 다음 *((char*)-1) = 'x';코드를 사용하여 여기에 대한 답변을
Shafik Yaghmour

이 질문에서 충돌보고 시스템에 대한 테스트 사례를 검색했습니다. 일반 런타임 중에 충돌보고기를 호출하고 덤프 덤프 전송을 강제로 중단해야했습니다. 감사!
Cory Trese

답변:


264

abort()기능은 아마도 가장 좋은 방법 일 것입니다. C 표준 라이브러리의 일부이며 "비정상적인 프로그램 종료"(예 : 치명적인 오류 또는 충돌)를 일으키는 것으로 정의됩니다.


14
충돌 abort()은 소멸자 또는 atexit함수를 호출하지 않지만 여기서는 중요하지 않습니다.
Xeo

139
@ Xeo : 소멸자와 atexits를 호출 하면 충돌이되지 않습니까?
Donal Fellows

abort()정답 이므로 'exit (-1);`이 허용되어야합니까?
asir6

9
아니요. 충돌을 일으키지 않기 때문에 수행 할 수없는 작업 만보고합니다.
보트 코더

Windows. GCC-5.4.0. 종료 코드 : 3. 오류 메시지 상자가 없습니다. 콘솔 메시지 : "이 응용 프로그램은 런타임을 비정상적으로 종료하도록 요청했습니다. 자세한 내용은 응용 프로그램 지원 팀에 문의하십시오."
Vadzim

113

시험:

raise(SIGSEGV);  // simulates a standard crash when access invalid memory
                 // ie anything that can go wrong with pointers.

발견 :

#include <signal.h>

3
단순한 구현 정의가 아닙니다. 신호를로 잡을 수 있습니다 signal(). 그러나 대부분의 정상적인 응용 프로그램은 그렇지 않습니다.
duskwuff -inactive-

12
응용 프로그램 내에서 일반적인 SIGSEGV와 동일한 방식으로 충돌합니다 (대부분의 응용 프로그램이 충돌하는 방식 임). 기본적으로 응용 프로그램을 종료하고 코어 파일을 생성합니다. 예, 핸들러를 설정할 수 있지만, 핸들러가 없다면 같은 방식으로 테스트하고 싶지 않습니다!
Martin York

1
일에 대한 raise(). 이를 통해 인수를 변경하여 다양한 유형의 예외를 테스트 할 수 있습니다.

3
선호하는 솔루션이지만 플랫폼에 따라 다릅니다.
Nadim Farhat

@NadimFarhat : 어떤 식 으로든. 신호는 모든 플랫폼에서 신호입니다.
Martin York

74

0으로 나누면 응용 프로그램이 중단됩니다.

int main()
{
    return 1 / 0;
}

29
컴파일러가 얼마나 영리한 지에 따라 컴파일 타임에 포착됩니다. Visual Studio 2008이 이것을 C ++ 또는 C #으로 컴파일하지 않는다는 것을 알고 있습니다.
AidanO

2
컴파일하고 실행했습니다. .exe를 샌드 하시겠습니까?
Roee Gavirel

1
2010과 같은 Visual Studio 최신 버전의 릴리스 구성에서는 문제없이 실행됩니다. 나는 그것이 최적화라고 생각합니다.
tedyyu

2
iirc 그것은 팔에 충돌하지 않습니다
sherpya

2
이것은 정의되지 않은 동작이며 충돌이 보장되지 않습니다. 종종 컴파일러는 정의되지 않은 동작에 도달 할 수 없다고 가정합니다. 이로 main인해 ret명령을 포함하여 본문 이 완전히 삭제 될 수 있습니다 . 실행은 다음 기능에 속할 수 있습니다.
usr

64
*((unsigned int*)0) = 0xDEAD;

54
충돌이 보장되지는 않습니다.
Windows 프로그래머

8
@Windowsprogrammer : 아니요, 보장 되지 않습니다 . 그러나 어느 정상적인 OS 주소 0에서 메모리에 액세스하려고하는 응용 프로그램을 중지 시키지 않습니까?
Joachim Sauer

29
"하지만 어느 제정 OS가 주소 0에서 메모리에 액세스하려고하는 응용 프로그램을 중지시키지 않습니까?" -그것은 정말로 당신이 묻고 싶은 것이 아니지만 어쨌든 대답 할 것입니다. 일부 컴퓨터에는 주소 0에 RAM이 있으며 프로그램에서 값을 저장하는 것이 완벽합니다. 보다 의미있는 질문은 "어떤 OS가 C ++ 구현이 널 포인터를 위해 예약 한 주소에서 메모리에 액세스하는 응용 프로그램을 중지하지 않습니까?"입니다. 이 경우 나는 아무것도 모른다. 그러나 원래 프로그램은 OS가 아닌 C ++ 언어에 관한 것입니다.
Windows 프로그래머

6
정의되지 않은 동작입니다. 이것이 아무것도하지 않는 것이 완벽합니다. 충돌하지 않는 머신 : Z80 시리즈 프로세서를 실행하는 모든 것 (제 Z80a는 아무것도하지 않습니다).
Martin York

28
이것이 충돌을 보장 하지는 않지만 C ++에서 가장 일반적인 충돌 유형 중 하나입니다 . 따라서 충돌을 시뮬레이션하려면이 작업을 수행 할 수있는 "진정한"방법입니다.
Chris Burt-Brown

53

글쎄, 우리는 스택 오버플로 에 있습니까?

for (long long int i = 0; ++i; (&i)[i] = i);

(어떤 표준에 의해서도 충돌이 보장되지는 않지만 수용된 답변을 포함하여 제안 된 답변 SIGABRT은 어쨌든 잡힐 수 있습니다. 실제로 이것은 모든 곳에서 충돌합니다.)


4
보호되지 않은 코드 페이지가있는 시스템에서 재미 있다는 것을 알 수 있으며 실수로 아무것도하지 않는 무한 루프 인 코드로 프로그램을 덮어 씁니다. 가능성은 높지 않지만 가능성은 매우 높습니다.
Martin York

@Loki : 모든 4000 번째 바이트에서 읽은 경우 어떻게됩니까? 충돌이 덜 일어날까요? 확실히 덜 위험합니다.
Mooing Duck

70
충돌 알고리즘은 O (1)이 아닙니다!
Anton Barkovsky

@MooingDuck : 난 그냥 재미있는 의견을 말하고 있습니다. 그것을 심각하게 받아들이지 마십시오 :-) 그러나 누군가가 재미있는 것을 한 일련의 지침을 발견하면 흥미로울 것입니다.
Martin York

1
@LokiAstari : 당신은 절대적으로 맞습니다. (&i)[i] += !i대신에 대해 생각하고 있었지만 컴파일러가 영리하고 충분히 최적화해야 할까봐 두려웠습니다. :-)
sam hocevar

35
 throw 42;

그냥 대답 ... :)


1
Windows. GCC-5.4.0. 종료 코드 : 3. 오류 메시지 상자가 없습니다. 콘솔 메시지 : " 'int'인스턴스를 던진 후 종료가 호출되었습니다.이 응용 프로그램은 런타임을 비정상적으로 종료하도록 요청했습니다. 자세한 정보는 응용 프로그램 지원 팀에 문의하십시오."
Vadzim

15

assert(false); 꽤 좋습니다.

ISO / IEC 9899 : 1999에 따르면 NDEBUG가 정의되지 않은 경우 충돌이 보장됩니다.

NDEBUG가 정의되면 [...] assert 매크로는 다음과 같이 간단하게 정의됩니다.

#define assert(ignore) ((void)0)

어설 션 매크로는 포함될 때마다 NDEBUG의 현재 상태에 따라 재정의됩니다.

[...]

assert 매크로는 진단 테스트를 프로그램에 넣습니다. [...] 식 (스칼라 형식을 가짐)이 [...] 인 경우 그런 다음 중단 기능을 호출합니다.


VC 2005가 어설 션을 사용하여 디버그와 릴리스간에 다르게 동작하는 것을 모호하게 기억합니까?
Tom Kerr

8
@Tom assert((void)0)릴리스 모드 와 동일 합니다.
세스 카네기

2
@SethCarnegie NDEBUG 정의가 정의되지 않는 경우에만 이것으로 무엇이 잘못되었는지 보지 않겠습니까? Dans 대답은 꽤 공정한 IMHO였습니다.
Adrian Cornish

@AdrianCornish 나는 Tom Kerr의 질문에만 대답했지만이 대답은 잘못되었다고 말하지 않았습니다. 나는이 답변을 공감하지 않았다.
세스 카네기

3
왜 그가이 테스트 코드의 "릴리스"빌드를하는지 모르겠습니다.
Joel B

11

크래시는 정의되지 않은 동작을 호출하는 증상이므로 정의되지 않은 동작을 호출하면 크래시를 포함하여 무엇이든 발생할 수 있으므로 실제로 프로그램을 크래시하고 싶지는 않지만 디버거에 빠지게한다고 생각합니다. 가장 휴대하기 쉬운 방법은 아마도abort() .

raise(SIGABRT)효과는 동일 하지만 작성하는 것이 더 좋습니다. 그러나에 대한 신호 처리기를 설치하면 두 가지 방법을 모두 가로 챌 수 있습니다 SIGABRT. 따라서 상황에 따라 다른 신호를 발생 시키거나 필요로 할 수도 있습니다. SIGFPE, SIGILL, SIGINT, SIGTERM또는SIGSEGV 이동하는 방법이 될 수도 있지만 그들은 모두 가로 챌 수 있습니다.

이식성이 떨어지면 SIGBUS리눅스에서 사용 하는 것과 같이 선택의 폭이 넓어 질 수 있습니다 .


1
나는 그가 디버거를 원한다는 것을 정말로 의심한다. 그는 충돌하는 프로그램의 호출자가 자신의 길을 보냈을 때 어떤 일이 발생하는지 테스트하고 싶어하는 것 같습니다. 어느 것이 매우 합리적입니까?
Donal Fellows

9

내가 가진 유일한 플래시는 abort () 함수입니다. .

이것은 비정상적인 프로그램 termination.It와 프로세스가 생성 중단 SIGABRT 신호 기본적으로 프로그램 environment.The 프로그램이 종료 호스트 실패한 종료 에러 코드를 반환 종료 원인 소멸자를 실행하지 않고 자동으로 또는 정적 저장 기간의 개체를 그리고 atexit (프로그램이 종료되기 전에 exit ()에 의해 호출 됨) 함수 를 호출 하지 않고 . 발신자에게 반환되지 않습니다.


9

답은 플랫폼에 따라 다르며 목표에 따라 다릅니다. 그러나 여기 모질라 자바 스크립트 크래쉬 함수가 있습니다.

static JS_NEVER_INLINE void
CrashInJS()
{
    /*
     * We write 123 here so that the machine code for this function is
     * unique. Otherwise the linker, trying to be smart, might use the
     * same code for CrashInJS and for some other function. That
     * messes up the signature in minidumps.
     */

#if defined(WIN32)
    /*
     * We used to call DebugBreak() on Windows, but amazingly, it causes
     * the MSVS 2010 debugger not to be able to recover a call stack.
     */
    *((int *) NULL) = 123;
    exit(3);
#elif defined(__APPLE__)
    /*
     * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
     * trapped.
     */
    *((int *) NULL) = 123;  /* To continue from here in GDB: "return" then "continue". */
    raise(SIGABRT);  /* In case above statement gets nixed by the optimizer. */
#else
    raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */
#endif
}

2
완전히 삭제하고 대신 jQuery를 사용해야합니다.
Thomas Weller

1
이것은 정의되지 않은 동작이며 충돌이 보장되지 않습니다. 종종 컴파일러는 정의되지 않은 동작에 도달 할 수 없다고 가정합니다. 이 경우 최소한 충돌하는 줄이 삭제되고 다른 코드도 삭제 될 수 있습니다.
usr

8

여기에 게시 된 많은 답변이있어서 작업을 끝내기 위해 운이 좋은 경우에 빠질 것이지만 100 % 결정적인 충돌은 없습니다. 일부는 하나의 하드웨어와 OS에서 충돌하지만 다른 하나는 충돌하지 않습니다. 그러나 공식 C ++ 표준에 따라 충돌을 일으키는 표준 방법이 있습니다.

C ++ 표준 ISO / IEC 14882 §15.1-7 에서 인용 :

예외 처리 메커니즘이 예외 객체의 초기화를 완료 한 후 예외에 대한 핸들러를 활성화하기 전에 예외를 통해 종료되는 함수를 호출하면 std :: terminate가 호출됩니다 (15.5.1).

struct C {
    C() { }
    C(const C&) {
        if (std::uncaught_exceptions()) {
            throw 0; // throw during copy to handler’s exception-declaration object (15.3)
        }
    }
};
int main() {
    try {
    throw C(); // calls std::terminate() if construction of the handler’s
    // exception-declaration object is not elided (12.8)
    } catch(C) { }
}

나는 이것을 설명하기 위해 작은 코드를 작성 했으며 여기 에서 Ideone 에서 찾고 시도 할 수 있습니다 .

class MyClass{
    public:
    ~MyClass() throw(int) { throw 0;}
};

int main() {
  try {
    MyClass myobj; // its destructor will cause an exception

    // This is another exception along with exception due to destructor of myobj and will cause app to terminate
     throw 1;      // It could be some function call which can result in exception.
  }
  catch(...)
  {
    std::cout<<"Exception catched"<<endl;
  }
  return 0;
}

ISO / IEC 14882 §15.1 / 9 언급은 try 블록없이 throw하여 중단을 암시 적으로 호출합니다.

현재 처리중인 예외가없는 경우 피연산자가없는 throw-expression을 실행하면 std :: terminate ()가 호출됩니다.

다른 것들은 다음과 같습니다 : 소멸자로부터 던지기 : ISO / IEC 14882 §15.2 / 3


7
*( ( char* ) NULL ) = 0;

이로 인해 분할 오류가 발생합니다.


10
충돌이 보장되지는 않습니다.
Windows 프로그래머

23
"대신 어떻게 될까요?" -대신에 무슨 일이든 일어날 수 있습니다. 동작은 정의되어 있지 않으므로 구현시 프로그램 변수 중 하나에 0을 할당하거나 프로그램 변수 중 하나에 42를 할당하거나 하드 드라이브를 포맷하고 프로그램을 계속 실행할 수 있습니다.
Windows 프로그래머

7
( "Windows 프로그래머"를 계속 생각하면) 컴퓨터가 폭발하거나 컴퓨터가 생동감있게되어 인류를 사로 잡을 수 있습니다. 또는 ... 99.9 %로 충돌하며 아무도 책임을지지 않기 때문에 "정의되지 않은 동작"으로 정의됩니다.
Roee Gavirel

1
실제로, 그것은 심지어 정의되지 않은 행동을한다고 보장하지는 않습니다. 그것은 완전히 정의되고 제대로 작동 할 수 있습니다. 다음 코드를 고려하십시오. pastebin.com/WXCtTiDD (Linux에서 루트로 테스트 한 경우 일부 구성 변경을 수행하는 경우 루트 사용자가 아닌 사용자도이를 수행 할 수 있습니다. wiki.debian.org/mmap_min_addr )
cha0site

2
@ cha0site : 표준에 의해 정의되지 않은 동작이 보장됩니다. 널 포인터를 참조하지 않기 때문입니다. 리눅스에서 관찰 한 행동은 "정의되지 않은 행동"이라는 우산 아래 허용됩니다
Ben Voigt

6

이것은 누락되었습니다 :

int main = 42;

1
그렇습니다. 그러나 당신이 그것을 실행할 때 그것은 놀라운 일을합니다.
Joshua

5

데드 루프 재귀 메서드 호출에 의한 스택 오버플로는 어떻습니까?

#include <windows.h>
#include <stdio.h>

void main()
{
    StackOverflow(0);
}

void StackOverflow(int depth)
{
    char blockdata[10000];
    printf("Overflow: %d\n", depth);
    StackOverflow(depth+1);
}

Microsoft KB의 원본 예 참조


4
충분한 스마트 컴파일러가 사용되지 않은 스택 할당과 테일 콜을 모두 최적화하지 못하게하는 이유는 무엇입니까?
JB.

@JB : 기존 컴파일러 최적화 로직에 익숙하지 않기 때문에 불행히도 전혀 모른다
sll

8
글쎄, 최적화 수준 -O2 이상에서 gcc 4.6.0으로 컴파일하면 잘 최적화됩니다. segfault에 -O1 이하가 필요합니다.
JB.

@Abhinav : C ++로 예제로 표현 된이 모든 방법으로 답을 게시하십시오 :)
sll

5

문자열 리터럴이 읽기 전용 메모리에 저장되기 때문에 Linux 시스템에서 충돌이 발생합니다.

0[""]--;

그건 그렇고, g ++은 이것을 컴파일하지 않습니다. 컴파일러는 점점 더 똑똑해지고 있습니다 :)


4
int i = 1 / 0;

귀하의 컴파일러는 아마 이것에 대해 경고합니다, 그러나 GCC 4.4.3에서 잘 컴파일이 것이다 아마 로 아마 SIGSEGV (메모리 세그먼트 위반)로 실제 응용 프로그램에서 같은 가능성이없는 SIGFPE (부동 소수점 예외), 원인 다른 답변은 원인이지만 여전히 충돌입니다. 제 생각에 이것은 훨씬 더 읽기 쉽습니다.

우리가 속이고 사용하려는 경우 다른 방법 signal.h은 다음 과 같습니다.

#include <signal.h>
int main() {
    raise(SIGKILL);
}

이것은 SIGSEGV와 대조하여 서브 프로세스를 종료시킵니다.


2
충돌이 보장되지는 않습니다.
Windows 프로그래머

11
C ++ 언어는 1 / 0이 SIGFPE를 유발한다고 보장하지 않습니다. 동작이 정의되지 않았습니다. 구현은 결과가 42라고 말할 수 있습니다.
Windows 프로그래머

1
동작이 정의되지 않은 경우 구현은 원하는대로 수행 할 수 있습니다. C ++ 언어는 크래시 덤프를 작성하기위한 구현을 막거나 요구하지 않으며, C ++ 언어는 42 등을 할당하기위한 구현을 막거나 요구하지도 않습니다.
Windows 프로그래머

2
@Giorgio 하드웨어에 자동으로 트래핑 할 방법이없는 경우에도 컴파일러는 적어도 두 개의 명령어를 내보내도록 강제합니다. 그 중 하나는 분기입니다. 부서 비용이 거의 두 배가됩니다. 모두 그런 비용을 지불합니다. 선택적이고 원하는 경우 항상 라이브러리 기능을 사용할 수 있습니다. 선택 사항이 아니고 원하지 않으면 비용을 지불하게됩니다.
Flexo

2
@Giorgio : 나는 100,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 * 10 ^ 1000000 분열을 수행하는 응용 프로그램이 있습니다. 컴파일러가 이것을 알 수있는 방법이 없지만 이들 중 0이 0으로 나눌 것이라는 사실을 알고 있습니다. 컴파일러가 0으로 나누기 검사를 심는 것을 원하지 않습니다 .
Martin York

4

이것은 위의 답변에 제시 된 중단의 더 보장 된 버전입니다. sigabrt가 차단 된 상황을 처리합니다. 실제로 프로그램 중단의 기본 조치가있는 중단 대신 모든 신호를 사용할 수 있습니다.

#include<stdio.h>
#include<signal.h>
#include<unistd.h> 
#include<stdlib.h>
int main()
{
    sigset_t act;
    sigemptyset(&act);
    sigfillset(&act);
    sigprocmask(SIG_UNBLOCK,&act,NULL);
    abort();
}

3
int* p=0;
*p=0;

이것도 충돌해야합니다. Windows에서는 AccessViolation과 충돌하고 모든 OS에서 동일하게 수행해야합니다.


5
on all OS-es아니요, 보호되지 않은 OS (예 : MS-DOS)에서는 충돌하지 않습니다. 실제로 주소 0에 문제 있는 경우 가 있습니다 ! x86 리얼 모드의 경우 인터럽트 벡터 테이블의 주소는 0입니다.
ikh

Irix에서는 충돌하지 않았습니다. 우리는 심지어 도착하지 않았습니다 어디 우리가 리눅스 (해당 코드를 포팅 할 때 나는 슬프게 깨달았다 main().
Scheff를

3

Breakpad에서 Google이 제공하는 스 니펫입니다.

  volatile int* a = reinterpret_cast<volatile int*>(NULL);
  *a = 1;

1
Breakpad를 테스트하고 있기 때문에 이것이 내가 원하는 것입니다! 일부 Breakpad 미니 덤프는 충돌을 일으키는 코드의 줄을 가리키는 스택 추적을 생성하지 않음을 발견했습니다. 이것은 그렇기 때문에 좋은 poc 테스트로 사용할 수 있습니다.
BuvinJ


2

이 질문에 이미 답변이 있지만 ...

void main(){
    throw 1;
}

또는... void main(){throw 1;}


2

시스템이 읽기 전용 메모리 블록을 지원하지 않으면 읽기 전용 메모리에 쓰면 분할 오류가 발생합니다.

int main() {
    (int&)main = 0;
}

Windows 7의 MingGW 5.3.0 및 Linux Mint의 GCC로 테스트했습니다. 다른 컴파일러와 시스템도 비슷한 효과를 낸다고 가정합니다.


1

또는 우리가 밴드 마차를 타고 있기 때문에 또 다른 방법입니다.

무한 재귀의 사랑스러운 조각. 스택을 날려 버립니다.

int main(int argv, char* argc)
{
   return main(argv, argc)
}

인쇄합니다 :

분할 오류 (코어 덤프)


13
main자신을 호출하는 것은 실제로 알 수없는 경우 정의되지 않은 동작입니다. :) 또한 꼬리 재귀가 스택을 날려 버릴 수 는 없습니다 . "보증인"을 원하면 재귀 호출 후 무언가 를 수행해야 합니다 . 그렇지 않으면 컴파일러가 재귀를 무한 루프로 최적화 할 수 있습니다.
fredoverflow

0

아직 언급되지 않은 것 :

((void(*)())0)();

이것은 널 포인터를 함수 포인터로 취급 한 다음 호출합니다. 대부분의 방법과 마찬가지로 프로그램 충돌을 보장하지는 않지만 OS가이를 검사하지 않고 프로그램이 다시 돌아올 가능성은 무시할 수 있습니다.


3
OS 시작 코드가 주소 0에 효과적으로 매핑되기 때문에 재부팅이 발생할 것이라는 여러 컴퓨터를 알고 있습니다. 모든 것이 PC처럼 작동한다고 가정하지 마십시오. 충돌이라고 말할 수는 있지만 시작시 모든 상태가 지워 지므로 디버그 할 수 없으므로 유용하지 않습니다.
Martin York

@Loki Astari : 나는 이것이 크래시라고 말하지 않을 것입니다. 이로 인해 크래시가 발생할 수 있다면 디버깅중인 프로그램도 테스트 될 수 있습니다. 다른 한편으로, 나는 어떤 기계가 파이썬을 실행할 수 있는지 궁금합니다.
Anton Golov

나는 당신이 요점을 놓쳤다 고 생각합니다. 나는 0에서 OS 코드를 보았습니다. 정상적인 정상 코드를 실행하여 0에서 잘 작동하는 시스템이 없다는 것을 의미하지는 않습니다. 또는 0의 바이트가 반환을위한 opcode 일 수 있습니다.
Martin York

0의 OS 코드를 알고 있습니다. 그것이 0의 바이트가 반환의 opcode가 될 것이라고 강력하게 의심하는 이유 중 하나입니다. 프로그램은 더 이상 명확하게 실행되지 않고 일반적인 방식으로 종료되지 않았습니다. 즉 충돌이 발생했습니다. 만약 이것이 asker에게 충분하지 않다면, 나는 그에게 스스로 의견을 제시 할 것으로 기대합니다.
Anton Golov

2
컴퓨터의 OS 코드 만 알고 있습니다. 내가 말하려는 것은 그것이 당신에게 실패 할 수 있다는 것입니다. 그러나 그것은 아무 의미가 없습니다. 거기에는 많은 시스템이 있습니다. 나는 그들 중 일부가 이것이 작동 할 것이라고 확신한다 머신 / OS 특정 동작에 의존하는 것은 나쁜 생각이며 장기적으로 유지 관리 문제를 유발합니다. 이 사이트의 아이디어는 좋은 코드를 홍보하는 것입니다.
Martin York

0
void main()
{

  int *aNumber = (int*) malloc(sizeof(int));
  int j = 10;
  for(int i = 2; i <= j; ++i)
  {
      aNumber = (int*) realloc(aNumber, sizeof(int) * i);
      j += 10;
  }

}

이것이 충돌하기를 바랍니다. 건배.


0
int main()
{
    int *p=3;
    int s;
    while(1) {
        s=*p;
        p++;
    }
}

2
약간의 설명이 필요합니다 :)
olyv

1
프로세스가 다른 프로세스의 메모리에 액세스 할 수 없으므로 p 포인터는 프로그램의 주소 공간을 넘어 메모리 오류가됩니다. 이로 인해 프로그램이 중단됩니다. 포인터 p는 주소 공간에서 임의의 위치를 ​​가리키고 있으며, 어느 시점에서 무한 증가하고 역 참조되면 다른 프로그램의 (프로세스) 주소 공간을 가리 킵니다. 시간이 지나면 충돌합니다.
sc_cs

또는 가설 적으로 정수 오버플로를 달성하고 무한대로 실행됩니다. 더 빨리 충돌하기 위해 또는 각각의 최대 값에서 시작 long long하거나 그 size_tp가까운 값으로 시작 하려고합니다 . 이 경우에도 여전히 충돌이 보장되지는 않습니다.
Patrick Roberts

0

이를 수행하는 세련된 방법은 순수한 가상 함수 호출입니다.

class Base;

void func(Base*);

class Base
{
public:
   virtual void f() = 0;
   Base() 
   {
       func(this);
   }
};

class Derived : Base
{
   virtual void f()
   {
   }
};

void func(Base* p)
{
   p->f();
}


int main()
{
    Derived  d;
}

gcc로 컴파일하면 다음과 같이 인쇄됩니다.

순수한 가상 메소드

활성 예외없이 호출 종료

중단됨 (코어 덤프)


0

c ++에서 어셈블리를 사용할 수 code 있지만 INT 3 x86 시스템 전용 이지만 다른 시스템에는 다른 트랩 / 브레이크 포인트 명령이있을 수 있습니다.

int main()
{
    __asm int 3;

    return 0;
}

INT 3 OS에 의해 설정된 인터럽트 벡터를 호출하고 인터럽트 벡터를 호출합니다.


0

GCC 또는 clang에서 __builtin_trap ()을 사용하거나 MSVC에서 __debugbreak ()를 사용하십시오. 이러한 중단 점 / 트랩을 처리하지 않으면 처리되지 않은 중단 점 예외 / 충돌이 발생합니다. abort () 또는 exit ()를 사용하는 다른 제안 : 다른 스레드에서 처리 할 수 ​​있으므로 충돌을 전파 한 스레드의 스택을보기가 더 어려워집니다.


-2
char*freeThis;
free(freeThis);

초기화되지 않은 포인터를 해제하는 것은 정의되지 않은 동작입니다. 많은 플랫폼 / 컴파일러에서 freeThis임의의 값을 갖습니다 (이전에 해당 메모리 위치에 있던 값). 해제하면 시스템이 해당 주소에서 메모리를 해제하도록 요청하며, 이로 인해 일반적으로 분할 오류가 발생하고 프로그램이 중단됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.