c++ 비주얼 - 2GB보다 큰 코드로 GCC 컴파일 오류




스튜디오 윈도우 (10)

따라서이 텍스트를 생성하는 프로그램이 이미 있습니다.

prefactor = +s.ds8*s.ds10*ti[0]->value();
expr = ( - 5/243.*(s.x14*s.x15*csc[49300] + 9/10.*s.x14*s.x15*csc[49301] +
       1/10.*s.x14*s.x15*csc[49302] - 3/5.*s.x14*s.x15*csc[49303] -...

double csc19295 =       + s.ds0*s.ds1*s.ds2 * ( -
       32*s.x12pow2*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
       32*s.x12pow2*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
       32*s.x12pow2*s.x15*s.x35*s.x45*s.mWpowinv2 -...

권리?

모든 함수가 비슷한 "형식"(n 번 m 번 곱하고 결과를 추가하거나 비슷한 경우)을 수행하면 다음과 같이 할 수 있다고 생각합니다.

  • 생성기 프로그램을 문자열 대신 출력 오프셋으로 변경하십시오 (예 : 문자열 "s.ds0"대신 offsetof(ProcessVars, ds0) 생성 offsetof(ProcessVars, ds0)
  • 그러한 오프셋의 배열을 만든다.
  • 위의 배열과 구조체 포인터의 기본 주소를 받아들이고 결과를 생성하는 평가기를 작성하십시오

array + evaluator는 함수 중 하나와 동일한 논리를 나타내지 만 평가자 만 코드가됩니다. 배열은 "데이터"이며 런타임에 생성되거나 디스크에 저장되고 청크 또는 메모리 매핑 된 파일로 저장 될 수 있습니다.

예를 들어 func1의 경우, scsc 의 기본 주소에 액세스 할 수있는 경우 평가기를 통해 함수를 다시 작성하는 방법과 상수 및 가져올 기본 주소에 추가해야하는 오프셋과 같은 벡터를 사용하는 방법을 상상해보십시오 ~ x14 , ds8csc[51370]

많은 수의 기능에 전달한 실제 데이터를 처리하는 방법을 설명하는 새로운 "데이터"형식을 만들어야합니다.

나는 약 2.8GB의 객체 코드를 가지고있는 엄청난 수의 함수를 가지고있다. (불행하게도, 과학적 컴퓨팅 ...)

필자가 링크를 시도 할 때 relocation truncated to fit: R_X86_64_32S 오류 relocation truncated to fit: R_X86_64_32S 될 것으로 예상됩니다. 컴파일러 플래그 -mcmodel=medium 하여 우회 -mcmodel=medium 합니다. 추가로 링크 된 모든 라이브러리는 -fpic 플래그로 컴파일됩니다.

그래도 오류가 지속되고 내가 링크 한 일부 라이브러리가 PIC로 컴파일되지 않는다고 가정합니다.

여기에 오류가 있습니다.

/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x12): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_fini'     defined in .text section in /usr/lib64/libc_nonshared.a(elf-init.oS)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x19): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_init'    defined in .text section in /usr/lib64/libc_nonshared.a(elf-init.oS)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crti.o: In function    `call_gmon_start':
(.text+0x7): relocation truncated to fit: R_X86_64_GOTPCREL against undefined symbol      `__gmon_start__'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtbegin.o: In function `__do_global_dtors_aux':
crtstuff.c:(.text+0xb): relocation truncated to fit: R_X86_64_PC32 against `.bss' 
crtstuff.c:(.text+0x13): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in /usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtend.o
crtstuff.c:(.text+0x19): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0x28): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x38): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x3f): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0x46): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x51): additional relocation overflows omitted from the output
collect2: ld returned 1 exit status
make: *** [testsme] Error 1

내가 링크하는 시스템 라이브러리 :

-lgfortran -lm -lrt -lpthread

문제를 찾을 수있는 단서가 있습니까?

편집 : 우선, 토론 해 주셔서 감사합니다 ... 조금 명확히하기 위해,이 같은 별도의 개체 파일에 수백 가지 기능 (각각 약 1 MB의 크기가 별도의) :

double func1(std::tr1::unordered_map<int, double> & csc, 
             std::vector<EvaluationNode::Ptr> & ti, 
             ProcessVars & s)
{
    double sum, prefactor, expr;

    prefactor = +s.ds8*s.ds10*ti[0]->value();
    expr =       ( - 5/243.*(s.x14*s.x15*csc[49300] + 9/10.*s.x14*s.x15*csc[49301] +
           1/10.*s.x14*s.x15*csc[49302] - 3/5.*s.x14*s.x15*csc[49303] -
           27/10.*s.x14*s.x15*csc[49304] + 12/5.*s.x14*s.x15*csc[49305] -
           3/10.*s.x14*s.x15*csc[49306] - 4/5.*s.x14*s.x15*csc[49307] +
           21/10.*s.x14*s.x15*csc[49308] + 1/10.*s.x14*s.x15*csc[49309] -
           s.x14*s.x15*csc[51370] - 9/10.*s.x14*s.x15*csc[51371] -
           1/10.*s.x14*s.x15*csc[51372] + 3/5.*s.x14*s.x15*csc[51373] +
           27/10.*s.x14*s.x15*csc[51374] - 12/5.*s.x14*s.x15*csc[51375] +
           3/10.*s.x14*s.x15*csc[51376] + 4/5.*s.x14*s.x15*csc[51377] -
           21/10.*s.x14*s.x15*csc[51378] - 1/10.*s.x14*s.x15*csc[51379] -
           2*s.x14*s.x15*csc[55100] - 9/5.*s.x14*s.x15*csc[55101] -
           1/5.*s.x14*s.x15*csc[55102] + 6/5.*s.x14*s.x15*csc[55103] +
           27/5.*s.x14*s.x15*csc[55104] - 24/5.*s.x14*s.x15*csc[55105] +
           3/5.*s.x14*s.x15*csc[55106] + 8/5.*s.x14*s.x15*csc[55107] -
           21/5.*s.x14*s.x15*csc[55108] - 1/5.*s.x14*s.x15*csc[55109] -
           2*s.x14*s.x15*csc[55170] - 9/5.*s.x14*s.x15*csc[55171] -
           1/5.*s.x14*s.x15*csc[55172] + 6/5.*s.x14*s.x15*csc[55173] +
           27/5.*s.x14*s.x15*csc[55174] - 24/5.*s.x14*s.x15*csc[55175] +
           // ...
           ;

        sum += prefactor*expr;
    // ...
    return sum;
}

객체 s 는 상대적으로 작고 필요한 상수 x14, x15, ..., ds0, ... 등을 유지하는 반면 ti 는 외부 라이브러리에서 double을 반환합니다. 보시다시피, csc[] 는 미리 계산 된 값의지도로, 다음 형식의 개별 객체 파일 (각각 ~ 1MB 크기로 수백 개 정도)로 평가됩니다.

void cscs132(std::tr1::unordered_map<int,double> & csc, ProcessVars & s)
{
    {
    double csc19295 =       + s.ds0*s.ds1*s.ds2 * ( -
           32*s.x12pow2*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x15*s.x35*s.x45*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x35*s.x45*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.mbpow4*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.x35*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.x45*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35*s.mbpow4*s.mWpowinv2 +
           32*s.x12pow2*s.x35pow2*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35pow2*s.x45*s.mWpowinv2 +
           64*s.x12pow2*s.x35*s.x45*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35*s.x45pow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.mbpow4*s.mWpowinv2 +
           64*s.x12*s.p1p3*s.x15pow2*s.mbpow2*s.mWpowinv2 +
           96*s.x12*s.p1p3*s.x15*s.x25*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.x45*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.mbpow4*s.mWpowinv2 +
           32*s.x12*s.p1p3*s.x25pow2*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.x45*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x45*s.mbpow2 +
           64*s.x12*s.x14*s.x15pow2*s.x35*s.mWpowinv2 +
           96*s.x12*s.x14*s.x15*s.x25*s.x35*s.mWpowinv2 +
           32*s.x12*s.x14*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.x14*s.x15*s.x35pow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x15*s.x35*s.x45*s.mWpowinv2 +
           32*s.x12*s.x14*s.x25pow2*s.x35*s.mWpowinv2 +
           32*s.x12*s.x14*s.x25*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x25*s.x35pow2*s.mWpowinv2 -
           // ...

       csc.insert(cscMap::value_type(192953, csc19295));
    }

    {
       double csc19296 =      // ... ;

       csc.insert(cscMap::value_type(192956, csc19296));
    }

    // ...
}

그게 다야. 마지막 단계는 모든 func[i] 를 호출하고 결과를 합산하는 것입니다.

이것은 매우 특별하고 드문 경우입니다. 그렇습니다. 이것은 입자 물리학에 대한 고정밀 계산을 시도 할 때 사람들이 대처해야하는 것입니다.

EDIT2 : 나는 또한 x12, x13, 등등은 정말 상수가 아니라는 것을 추가해야합니다. 그들은 특정 값으로 설정되고 모든 함수가 실행되고 결과가 반환 된 다음 x12, x13 등의 새 집합이 선택되어 다음 값을 생성합니다. 그리고 이것은 10 ^ 5에서 10 ^ 6 번 ...

EDIT3 : 제안 및 토론 주셔서 감사합니다 지금까지 ... 어떻게 든 코드 생성시 루프를 롤백하려고합니다. 솔직히이 방법을 정확히 알지 못하지만, 이것이 최선의 방법입니다.

BTW, 나는 이것이 "과학적 컴퓨팅 - 최적화 할 수있는 방법이 아닙니다"뒤에 숨기려고하지 않았습니다. 이 코드의 기초는 내가 실제로 접근 할 수없는 "블랙 박스"에서 나오는 것이며, 게다가 모든 것이 간단한 예제로 훌륭하게 작동했으며, 실제로는 실제 상황에서 어떤 일이 일어날 지 압도 당하고 있다고 느낍니다. 세계적인 응용 프로그램 ...

EDIT4 : 그래서 컴퓨터 대수학 시스템 ( Mathematica )에서 표현식을 단순화하여 약 1만큼 csc 정의의 코드 크기를 줄였습니다. 코드를 생성하기 전에 다른 트릭을 적용하여 몇 가지 방법으로 크기를 줄이는 방법도 있습니다.이 방법을 사용하면이 부분을 약 100MB로 줄일 수 있습니다.

이제 당신의 대답과 관련이 있습니다 : 나는 CAS가 많은 도움이되지 않는 func 에서 루프를 다시 롤백하려고 노력하고 있지만 이미 아이디어가 있습니다. 예를 들어 x12, x13,... 과 같은 변수로 표현식을 정렬하면 csc 를 Python으로 구문 분석하고 서로 관련있는 테이블을 생성합니다. 그런 다음 최소한 이러한 부분을 루프로 생성 할 수 있습니다. 이것이 지금까지 가장 좋은 해결책 인 것 같아서, 나는 이것을 가장 좋은 대답으로 표시했다.

그러나 VJo에 대해서도 공을 들여야합니다. GCC 4.6은 실제로 잘 작동 하고 , 더 작은 코드를 생성하며 빠릅니다. 대형 모델을 사용하면 코드에서 그대로 작동합니다. 그래서 기술적으로 이것은 정답이지만 전체 개념을 바꾸는 것이 훨씬 더 나은 접근법입니다.

귀하의 제안과 도움에 감사드립니다. 관심있는 사람이 있으면 준비가 완료되는대로 최종 결과를 게시하겠습니다.

비고 : 몇 가지 다른 답변이 있습니다. 실행하려고하는 코드는 간단한 함수 / 알고리즘의 확장과 불필요한 불필요한 언 롤링에서 유래하지 않습니다. 실제로 일어나는 일은 우리가 시작하는 것들이 꽤 복잡한 수학적 객체이며 수치 계산 가능한 형태로 가져 오는 것이 이러한 표현을 생성한다는 것입니다. 문제는 실제로 기본 물리 이론에 있습니다. 중간 표현의 복잡성은 요인에 따라 달라 지지만,이 모든 것들을 물리적으로 측정 할 수있는 것, 즉 관찰 할 수있는 것으로 결합하면 표현의 기본을 구성하는 아주 작은 함수들로 끝납니다. ( "섭동 이론 (perturbation theory)"이라고 불리는 일반적이고 유일하게 이용 가능한 ansatz 대해서는이 점에서 분명히 "틀린"것이있다.) 우리는이 ansatz를 다른 수준으로 가져 오려고 노력한다. 이것은 분석적으로는 더 이상 가능하지 않으며 필요한 기능의 기초는 불명. 그래서 우리는 그것을 이렇게 무차별 적으로 시도합니다. 최선의 방법은 아니지만, 결국에는 물리학에 대한 우리의 이해에 도움이되는 한 가지 방법이 있습니다.

마지막 편집 : 모든 제안 덕분에 필자는 코드 크기를 상당히 줄였습니다. Mathematica와 코드 생성기의 수정을 사용하여 최상위 답변 라인을 따라 다소 단축되었습니다. :)

필자는 Mathematica로 csc 함수를 단순화하여 92 MB로 낮추었습니다. 이것은 환원 불가능한 부분입니다. 첫 번째 시도는 영원히 걸렸지 만 일부 최적화 후에는 이제 단일 CPU에서 약 10 분 만에 실행됩니다.

func 에 대한 효과는 극적이었습니다. 코드 크기가 약 9MB로 줄어들 었으므로 코드는 이제 100MB 범위로 합쳐집니다. 이제는 최적화를 실행하는 것이 좋으며 실행은 매우 빠릅니다.

다시 한 번, 여러분의 제안에 대해 모두 감사 드리며, 많이 배웠습니다.


몇 가지 제안 사항 : - 크기 (-Os)에 맞게 최적화하십시오. 인라인 함수 호출, 일반 함수 호출을 만듭니다. 문자열 풀링을 사용합니다.

여러 DLL (공유 객체, Linux의 경우 .so, Mac OS X의 경우 .dylib)로 분할 해보십시오. 그것들을 내릴 수 있는지 확인하십시오. 그런 다음 요구에 따라 물건을 적재하고 필요하지 않을 때 물건을 비우기 위해 무언가를 구현하십시오.

그렇지 않다면 코드를 다른 실행 파일로 나눠서 무언가를 사용하여 그들 사이에서 통신하십시오 (파이프, 소켓, 파일 쓰기 / 읽기). 서투른,하지만 어떤 옵션이 있습니까?

완전히 대안 : - JIT 와 함께 동적 언어를 사용하십시오. 내 머리 꼭대기에 LuaJIT 사용하고 Lua 나 코드를 가비지 수집 할 수있는 다른 언어 및 런타임에서 이러한 많은 표현식을 다시 작성 (다시 생성) 할 수 있습니다.

LuaJIT는 매우 효율적이며 어떤 경우 C / C ++을 때리고 때로는 매우 가깝습니다. (가끔 가비지 콜렉션 때문에 느려질 수도 있습니다.) 직접 확인하십시오.

http://luajit.org/performance_x86.html

거기에서 scimark2.lua 파일을 다운로드하고 "C"버전 (google it)과 비교하십시오. 종종 결과가 매우 비슷합니다.


링커는이 제한을 어떻게 든 넘긴 바이너리 내에서 32 비트 재배치 오프셋을 생성하려고 시도하고 있습니다. 주 프로그램의 주소 공간 요구 사항을 줄이십시오.

객체 코드의 일부 또는 대부분을 하나 이상의 라이브러리 (또는 -fpic / -fPIC로 컴파일)로 나눌 수 있습니까? 그런 다음이 libs에 링크되는 비 정적 바이너리를 생성하십시오. 라이브러리는 개별 메모리 블록에 저장되며 재배치 오프셋은 상대적 (32 비트)보다는 동적 / 절대 (64 비트)가됩니다.


이러한 측면의 프로그램을 사용하면 코드에 대한 캐시 누락이 런타임에 루핑 비용을 초과 할 가능성이 매우 높습니다. 나는 당신이 코드 생성기로 돌아가서 평가하고자하는 (즉, 하나는 D- 캐시에 적합 할 것 같은) 컴팩트 한 표현을 생성 다음 프로그램에서 인터프리터로 실행하도록 권장 할 것이다. 여전히 많은 수의 연산을 가지고있는 더 작은 커널을 배제 할 수 있는지를 알 수 있습니다. 그런 다음이를 해석 된 코드에서 '명령어'로 사용하십시오.


코드가 어떤 종류의 적응 형 깊이 메서드를 사용하여 수치 적 통합을 수행하는 것처럼 보입니다. 불행히도, 코드 생성기 (또는 코드 생성기의 작성자)는 패치 유형 마다 하나가 아닌 패치 당 하나의 함수를 생성하는 정도로 어리 석습니다 . 따라서, 컴파일 할 코드가 너무 많이 생성되어 컴파일 될 수 있다고하더라도 실행은 고통 스러울 것입니다. (아무 것도 공유되지 않고 항상 OS가 퇴거시킬 수 있기 때문에 디스크에서 객체 코드의 각 페이지를로드해야하는 고통을 상상할 수 있습니다. 쓸모없는 명령어 캐시는 말할 것도 없습니다.)

해결 방법은 모든 것을 언 롤링하는 것입니다. 이런 종류의 코드의 경우 복잡한 패턴의 데이터에 액세스하기위한 추가 명령어의 오버 헤드가 (아마도) 대형 기본 데이터 세트를 처리하는 비용으로 흡수 되므로 공유극대화 하려고합니다. 또한 코드 생성기가 기본적으로이 작업을 수행 할 수도 있고 과학자가 언 롤링 옵션을 보았을 때 (속도가 향상되는 경우가 있음)이를 모두 한꺼번에 켜고 이제는이 결과가 받아 들여 지도록 주장 할 수도 있습니다 컴퓨터에서 실제 제한 사항을 수락하고 기본적으로 생성되는 수치 적으로 올바른 버전을 사용하는 대신 그러나 코드 생성기가이를 수행하지 않는다면 기존 코드를 해킹 할 코드를 생성하십시오.

최종선 : 2.8GB의 코드를 컴파일하고 연결하는 것이 효과가 없으며 강제로 작동해서는 안됩니다. 다른 방법을 찾아라.


Linux에서 사용하는 x86-64 ABI 는 GOT 및 PLT의 64 비트 재배치 유형을 포함하여 이러한 크기 제한을 피하기 위해 특별히 "대형 모델"을 정의합니다. (4.4.2 절의 표 및 3.5.5의 명령 시퀀스에서 사용 방법을 보여줍니다.)

gcc가 대형 모델을 지원하지 않기 때문에 함수가 2.8GB를 차지하므로 운이 없게됩니다. 할 수있는 일은 코드를 동적으로 링크 할 공유 라이브러리로 분리 할 수있는 방식으로 코드를 재구성하는 것입니다.

누군가가 제안했듯이 데이터를 코드에 집어 넣는 대신 (컴파일하고 링크하는 것), 코드가 거대하기 때문에 런타임에 파일을로드 할 수 있습니다 (일반 파일 또는 mmap 할 수 있음).

편집하다

대형 모델이 gcc 4.6에서 지원되는 것처럼 보입니다 ( 이 페이지 참조 ). 시도해 볼 수는 있지만 위 코드는 코드 재구성에 적용됩니다.


나는 모두가하고 싶은 일을하는 다른 방법이 있어야한다는 데 동의한다고 생각합니다. 수백 메가 바이트 (기가 바이트)의 코드를 컴파일하여 멀티 기가 바이트 크기의 실행 파일에 연결하고 실행하면 매우 비효율적입니다.

내가 문제를 올바르게 이해한다면, 어떤 종류의 코드 생성기 G를 사용하여 func1...Ncsc1...M 을 생성한다. 당신이 원하는 것은 csc1...M 을 계산하고, 다른 입력에 대해 매회 1,000,000 회 반복을 실행할 때마다 s = func1 + func2 + ... + funcN . 당신은 fucn1...Ncsc1...M 과 어떻게 관련이 있는지를 지정하지 않았습니다.

이 모든 것이 사실이라면 문제를 머리에 맞춰 다른 방식으로 돌릴 수 있어야하며, 이는 훨씬 더 관리가 쉽고 더 빨라질 수도 있습니다 (즉, 실제로 시스템의 캐시를 작동시키는 것).

객체 파일 크기의 실용적인 문제 외에도 현재 프로그램은 데이터에 대한 액세스를 현지화하지 않고 (너무 많은 거대한 맵) 로컬 화 된 코드 실행 (매우 긴 함수가 너무 많음)이 없기 때문에 효율적이지 않습니다.

프로그램을 3 단계로 csc1...M 단계 1은 csc1...M 빌드하고 저장합니다. 2 단계는 한 번에 하나의 func 를 만들고 각 입력에 1,000,000 번 실행하고 결과를 저장합니다. 3 단계는 1,000,000 회 각각에 대해 저장된 func1...N 결과의 결과 합계를 찾습니다. 이 솔루션에 대한 좋은 점은 여러 독립적 인 시스템에서 쉽게 병렬로 만들 수 있다는 것입니다.

편집 : @bbtrb, 하나의 기능을 사용할 수 있고 하나의 csc를 사용할 수 있습니까? 그들은 매우 규칙적이고 압축 적으로 보입니다. 예를 들어, func1은 각각 1 개의 계수, 2 개의 s의 변수 색인 및 1 개의 csc 색인으로 구성된 표현식의 합계 인 것처럼 보입니다. 따라서 멋진 루프로 줄일 수 있습니다. 완전한 예제를 사용할 수 있다면 긴식이 아닌 루프로 압축하는 방법을 찾을 수있을 것이라고 확신합니다.


오류를 올바르게 읽은 경우 초기화 된 데이터 섹션이 한계를 넘기게됩니다 (코드 인 경우 IMHO 오류가 훨씬 더 많음). 대규모 데이터 배열이 있습니까? 그렇다면 동적으로 할당되도록 프로그램을 재구성 할 것입니다. 데이터가 초기화되면 구성 파일에서 읽습니다.

이것을보고 BTW :

(. 텍스트 + 0x20) : 정의되지 않은 'main'참조

다른 문제가 있다고 생각합니다.


데이터가 아닌 CODE가 너무 많아서 오류가 발생합니다! 예를 들어 _start 에서 참조되는 __libc_csu_fini (함수)가 표시되고 재배치가 맞게 잘립니다. 이것은 _start (프로그램의 참 진 엔트리 포인트)가 2GB의 범위만을 가진 SIGNED 32 비트 오프셋을 통해 해당 함수를 호출하려고한다는 것을 의미합니다. 오브젝트 코드의 총량이 ~ 2.8GB이므로 사실을 확인합니다.

데이터 구조를 재 설계 할 수 있다면 커다란 표현을 간단한 루프로 다시 작성함으로써 코드의 상당 부분을 "압축"할 수 있습니다.

또한 다른 프로그램에서 csc[] 를 계산하고 결과를 파일에 저장 한 다음 필요할 때로드 할 수 있습니다.


이것은 매우 광범위한 주제입니다. 기본적으로, 당신은 정말로 메모리 손상으로부터 복구 할 수 없지만, 당신은 적어도 즉시 실패 하려고 할 수 있습니다. 다음은 사용할 수있는 몇 가지 기술입니다.

  • 체크섬 상수 데이터 . 오랫동안 일정한 구성 데이터 (구성한 하드웨어 레지스터 포함)가있는 경우 초기화시 체크섬을 계산하고 주기적으로 확인하십시오. 불일치가 표시되면 다시 초기화하거나 재설정해야합니다.

  • 중복성이있는 변수를 저장하십시오 . 중요한 변수 x 가있는 경우 x1 , x2x3 값을 쓰고 (x1 == x2) ? x2 : x3 로 읽으 (x1 == x2) ? x2 : x3 (x1 == x2) ? x2 : x3 .

  • 프로그램 흐름 모니터링을 구현하십시오. 주요 루프에서 호출 된 중요한 함수 / 분기의 고유 한 값으로 전역 플래그를 XOR합니다. 방사능이없는 환경에서 100 %에 가까운 테스트 커버리지로 프로그램을 실행하면주기 마지막에 허용되는 플래그 값 목록을 얻을 수 있습니다. 편차가 보이면 재설정하십시오.

  • 스택 포인터를 모니터하십시오 . 기본 루프의 시작 부분에서 스택 포인터를 예상 값과 비교합니다. 이탈시 재설정.





c++ c gcc compiler-errors