C / C ++ 프로그램이 main () 전에 충돌 할 수있는 방법이 있습니까?
프로그램이 main () 전에 충돌 할 수있는 방법이 있습니까?
gcc를 사용하면 생성자 속성을 사용하여 함수에 태그를 지정할 수 있습니다 (이로 인해 함수가 이전에 실행 됨 main
). 다음 함수에서는 premain
전에 호출됩니다 main
.
#include <stdio.h>
void premain() __attribute__ ((constructor));
void premain()
{
fputs("premain\n", stdout);
}
int main()
{
fputs("main\n", stdout);
return 0;
}
따라서 충돌 버그가 premain
있으면 main
.
예, 적어도 Windows에서는. 프로그램이 DLL을 사용하는 경우 main()
시작 전에로드 할 수 있습니다 . DllMain
이러한 DLL 의 기능은 main()
. 오류가 발생하면 전체 프로세스가 중단되거나 충돌 할 수 있습니다.
C ++ 프로그램이있는 경우 main이 입력되기 전에 함수와 생성자를 통해 변수와 개체를 초기화 할 수 있습니다. 이러한 버그로 인해 프로그램이 중단 될 수 있습니다.
확실히 C ++에서; 컨 트럭 터가있는 정적 객체는 메인보다 먼저 호출됩니다.
c에 대해 잘 모르겠다
여기에 샘플이 있습니다
class X
{
public:
X()
{
char *x = 0;
*x = 1;
}
};
X x;
int main()
{
return 0;
}
이것은 메인 전에 충돌합니다
간단한 대답은 예 입니다.
보다 구체적으로, 이에 대한 두 가지 원인을 구별 할 수 있습니다. 나는 그것들을 구현 의존적 및 구현 독립적 이라고 부를 것 입니다.
환경에 전혀 의존하지 않는 한 가지 경우 는 여기에서 언급 한 C ++의 정적 개체의 경우입니다. 다음 코드는 전에 죽습니다 main()
.
#include <iostream>
class Useless {
public:
Useless() { throw "You can't construct me!"; }
};
static Useless object;
int main() {
std::cout << "This will never be printed" << std::endl;
return 0;
}
더 흥미로운 것은 플랫폼에 따른 원인 입니다. 일부는 여기에 언급되었습니다. 여기에서 몇 번 언급 된 것은 동적으로 연결된 라이브러리 (Windows의 DLL, Linux의 SO 등)의 사용이었습니다. OS의 로더가 이전에로드하면 main()
응용 프로그램이 이전에 죽을 수 있습니다 main()
.
이 원인의 일반적인 버전 모두에 대한 것을 이야기 이진의 진입 점을 호출하기 전에 수행을 당신의 진입 점을 ( main()
). 일반적으로 바이너리를 빌드 할 때 운영 체제의 로더가 바이너리를 실행하기 시작할 때 호출되는 매우 심각한 코드 블록이 있으며, 완료되면 main()
. 이 코드가 수행하는 일반적인 작업 중 하나는 C / C ++ 표준 라이브러리를 초기화하는 것입니다. 이 코드는 여러 가지 이유로 실패 할 수 있습니다 (할당하려는 모든 종류의 시스템 리소스 부족).
바이너리가 이전 main()
에 Windows에서 코드를 실행하는 한 가지 흥미로운 방법 은 TLS 콜백을 사용하는 것입니다 (Google에서 이에 대해 자세히 알려드립니다). 이 기술은 일반적으로 멀웨어에서 기본적인 안티 디버깅 트릭으로 발견됩니다 (이 트릭은 당시 ollydbg를 속이는 데 사용되었지만 여전히 작동하는지 알 수 없음).
요점은 귀하의 질문이 실제로 "바이너리를로드하면 사용자 코드가 코드 이전에 실행되도록하는 방법이 main()
있습니까?"와 동일하며 대답은 지옥입니다. 예!
main 이전에로드되는 공유 객체 (DLL)에 의존하는 모든 프로그램은 main 이전에 실패 할 수 있습니다.
Linux에서 동적 링커 라이브러리 (ld-*. so)의 코드는 main 이전에 라이브러리 종속성을 제공하기 위해 실행됩니다. 필요한 라이브러리를 찾을 수없는 경우 액세스를 허용하지 않는 권한이 있거나, 일반 파일이 아니거나, 프로그램을 링크 한 동적 링커가 언제 가져야한다고 생각하는 기호가없는 경우 프로그램을 연결하면 오류가 발생할 수 있습니다.
또한 각 라이브러리는 링크 될 때 일부 코드를 실행합니다. 이는 대부분 라이브러리가 더 많은 라이브러리를 링크해야하거나 일부 생성자를 실행해야 할 수 있기 때문입니다 (C 프로그램에서도 라이브러리는 일부 C ++ 또는 생성자를 사용하는 다른 것을 가질 수 있음). 또한 표준 C 프로그램은 이미 stdio 파일 stdin, stdout 및 stderr을 작성했습니다. 많은 시스템에서 이것도 닫힐 수 있습니다. 이것은 그들 (및 그들의 버퍼)이 malloc () ed되었고 실패 할 수 있음을 의미하는 free ()됨을 의미합니다. 또한 해당 FILE 구조가 나타내는 파일 설명자에 대해 다른 작업을 수행했을 수 있으며 이는 실패 할 수 있음을 나타냅니다.
OS가 프로그램에 전달 된 환경 변수 및 / 또는 명령 줄 인수 설정을 엉망으로 만드는 경우 발생할 수있는 다른 일이있을 수 있습니다. main 이전의 코드는 main을 호출하기 전에이 데이터와 관련이있을 가능성이 높습니다.
메인 이전에 많은 일이 발생합니다. 그들 중 누구라도 치명적인 방식으로 실패 할 수 있습니다.
확실하지 않지만 다음과 같은 전역 변수가있는 경우 :
static SomeClass object;
int main(){
return 0;
}
'SomeClass'생성자는 메인이 실행되기 전에 프로그램을 중단시킬 수 있습니다.
많은 가능성이 있습니다.
먼저, main이 실행되기 전에 실제로 무슨 일이 일어나는지 이해해야합니다.
- 동적 라이브러리로드
- 글로벌 초기화
- 일부 컴파일러, 일부 함수는 명시 적으로 실행할 수 있습니다.
이제이 중 하나가 여러 가지 방식으로 충돌을 일으킬 수 있습니다.
- the usual undefined behavior (dereferencing null pointer, accessing memory you should not...)
- an exception thrown > since there is no
catch
,terminate
is called and the program end
It's really annoying of course and possibly hard to debug, and that is why you should refrain from executing code before main
as much as possible, and prefer lazy initialization if you can, or explicit initialization within main
.
Of course, when it's a DLL failing and you can't modify it, you're in for a world of pain.
Sort of: http://blog.ksplice.com/2010/03/libc-free-world/
If you compile without standard library, like this: gcc -nostdlib -o hello hello.c
it won't know how to run main() and will crash.
Global and static objects in a C++ program will have their constructors called before the first statement in main() is executed, so a bug in one of the constructors can cause a crash.
This can't happen in C programs, though.
It depends what you mean by "before main", but if you mean "before any of your code in main is actually executed" then I can think of one example: if you declare a large array as a local variable in main, and the size of this array exceeds the available stack space, then you may well get a stack overflow
on entry to main, before the first line of code executes.
A somewhat contrived example would be:
int a = 1;
int b = 0;
int c = a / b;
int main()
{
return 0;
}
It's unlikely that you'd ever do something like this, but if you're doing a lot of macro-magic, it is entirely possible.
class Crash
{
public:
Crash( int* p )
{ *p = 0; }
};
static Crash static_crash( 0 );
void main()
{
}
Sure, if there's a bug in the operating system or the runtime code. C++ is particularly notorious for this behaviour, but it can still happen in C.
You haven't said which platform/libc. In the embedded world there are frequently many things which run before main()
- largely to do with platform setup - which can go wrong. (Or indeed if you are using a funky linker script on a regular OS, all bets are off, but I guess that's pretty rare.)
some platform abstraction libraries override (i personally only know of C++ libraries like Qt or ACE, which do this, but maybe some C libraries do something like that aswell) "main", so that they specify a platform-specific main like a int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow );
and setup some library stuff, convert the command line args to the normal int argc, char* argv[]
and then call the normal int main(int argc, char* argv[])
Of course such libraries could lead to a crash when they did not implement this correctly (maybe cause of malformed command line args).
And for people who dont know about this, this may look like a crash before main
I had faced the same issue. The root-cause found was.. Too many local variables(huge arrays) were initialized in the main process leading the local variables size exceeding 1.5 mb.
This results in a big jump as the stack pointer is quite large and the OS detects this jump as invalid and crashes the program as it could be malicious.
To debug this.
1. Fire up GDB
2. Add a breakpoint at main
3. disassemble main
4. Check for sub $0xGGGGGGG,%esp
If this GGGGGG value is too high then you will see the same issue as me.
So check the total size of all the local variables in the main.
Best suited example to crash a program before main
for stackoverflow:
int main() {
char volatile stackoverflow[1000000000] = {0};
return 0;
}
참고URL : https://stackoverflow.com/questions/2518415/is-there-any-way-a-c-c-program-can-crash-before-main
'programing tip' 카테고리의 다른 글
C에서 참조로 배열을 전달합니까? (0) | 2020.11.23 |
---|---|
언제 RuntimeException을 잡아도 괜찮습니까? (0) | 2020.11.23 |
jstl foreach는 마지막 레코드의 요소를 생략합니다. (0) | 2020.11.23 |
Entity Framework 컨텍스트를 Using 문에 넣어야합니까? (0) | 2020.11.22 |
클립 보드에 데이터를 안전하게 복사하기위한 플래시 기반 ZeroClipboard의 HTML5 대안? (0) | 2020.11.22 |