프로그램은 릴리스 빌드로만 충돌합니다. 디버그 방법은 무엇입니까?


95

여기에 "Schroedinger 's Cat"유형의 문제가 있습니다. 내 프로그램 (실제로는 내 프로그램의 테스트 스위트이지만 그럼에도 불구하고 프로그램)이 충돌하지만 릴리스 모드에서 빌드 될 때만 명령 줄에서 실행될 때만 발생합니다. . 원시인 디버깅 (즉, 모든 곳에서 불쾌한 printf () 메시지)을 통해 코드가 충돌하는 테스트 방법을 결정했습니다. 불행히도 실제 충돌은 일부 소멸자에서 발생하는 것 같습니다. 깨끗하게 실행되는 다른 소멸자.

Visual Studio 내에서이 프로그램을 실행하려고하면 충돌이 발생하지 않습니다. WinDbg.exe에서 시작할 때도 마찬가지입니다. 충돌은 명령 줄에서 시작할 때만 발생합니다. 이것은 Windows Vista, btw에서 발생하며 안타깝게도 지금 테스트 할 XP 시스템에 액세스 할 수 없습니다.

Windows가 스택 추적을 인쇄하도록하거나 프로그램이 깨끗하게 종료 된 것처럼 단순히 종료하는 이외의 다른 것을 인쇄 할 수 있다면 정말 좋을 것 입니다. 여기에서 더 의미있는 정보를 얻고이 버그를 수정하는 방법에 대한 조언이 있습니까?

편집 : 문제는 실제로이 게시물에서 자세히 설명하는 범위를 벗어난 배열로 인해 발생했습니다 . 이 문제를 찾는 데 도움을 주신 모든 분들께 감사드립니다!


그 테스트 방법의 샘플을 줄 수 있습니까?
akalenuk

죄송합니다. 코드는 너무 복잡해서 여기에 쉽게 붙여 넣을 수 없습니다. 앞서 언급했듯이 테스트 메서드 자체에서 발생하는 것이 아니라 나중에 소멸자가 발생합니다. 그러나이 메서드에는 초기화되지 않은 포인터 나 이와 유사한 것이 없습니다.
Nik Reiman

3
대부분의 답변은 추측에 불과합니다. 디버거를 연결하지 않고 충돌하는 릴리스 빌드를 분석하는 몇 가지 일반적인 기술이 있습니다. stackoverflow.com/a/18513077/214777?stw=2
Sebastian

당신의 잘못이 아닐 수도 있습니다. 최적화 수준 -O3가 g ++에서 위험합니까?
브렌트 Bradburn

답변:


127

C 또는 C ++ 프로그램이 디버거에서 제대로 실행되지만 외부에서 실행하면 실패하는 100 %의 사례에서, 그 원인은 함수 로컬 배열의 끝을지나 쓰기 때문입니다. (디버거는 스택에 더 많이 배치하므로 중요한 내용을 덮어 쓸 가능성이 적습니다.)


31
누군가이 남자에게 시가를 줘! 제 경우에는 P / Invoke 함수에 충분한 용량이없는 StringBuilder를 전달했습니다. 당신이 잠들 때 매직 마커로 당신의 얼굴에 누군가 글을 쓰는 것과 같다고 생각합니다. 눈 ... 그런 것. 이 팁에 감사드립니다!
Nicholas Piasecki

1
제 경우에는 Obj-C를 사용하는 ARM 프로세서의 정렬 문제로 밝혀졌습니다.
Almo 2013 년

1
11 년이 지난 지금도 여전히 사실입니다. 벡터를 예약하는 것을 잊지 마십시오.
dav

1
좋아, 그러면 실제로 디버그 할 수 있도록 디버그 모드의 동작을 어떻게 변경합니까?
Paul Childs

1
"이제 어디를보아야할지 알지만"디버그에서 작동하는 모든 것이 문제의 위치를 어떻게 알 수 있습니까 ? 대부분의 경우 귀하의 대답이 정확하다고 생각하고 무엇을 찾아야하는지 아는 것이 좋은 시작이라고 생각하지만 대규모 코드베이스를 통해 문제가 정확히 어디에 있는지 찾아내는 것은 엄청나게 많은 비용이들 수 있습니다.
Paul Childs

55

일반적으로 변수 초기화로 인해 발생하기 전에 이와 같은 문제가 발생했을 때. 디버그 모드에서 변수와 포인터는 자동으로 0으로 초기화되지만 릴리스 모드에서는 초기화되지 않습니다. 따라서 이와 같은 코드가 있으면

int* p;
....
if (p == 0) { // do stuff }

디버그 모드에서 if의 코드는 실행되지 않지만 릴리스 모드에서 p는 정의되지 않은 값을 포함합니다.이 값은 0 일 가능성이 낮으므로 코드가 자주 실행되어 충돌이 발생합니다.

초기화되지 않은 변수에 대한 코드를 확인합니다. 이것은 배열의 내용에도 적용될 수 있습니다.


일반적인 경우는 생성자 멤버 초기화 목록 중 하나에 멤버 변수를 넣는 것을 잊었습니다. 동일한 효과가 있지만 적절한 멤버 초기화를 찾아야한다는 것을 모르는 경우 찾기가 더 어렵습니다.
steffenj

1
디버그 모드에서 변수는 일반적으로 변수가 어떤 상태인지 표시하기 위해 디버깅에 사용할 수있는 일부 '컴파일러 정의 상수'로 초기화됩니다. 예 : NULL 또는 0xDeadBeef 포인터가 널리 사용됩니다.
Martin York

디버그 런타임은 일반적으로 메모리를 0이 아닌 값으로 초기화합니다. 특히 NULL 포인터 테스트로 인해 코드가 포인터가 NULL이 아닌 것처럼 작동하도록합니다. 그렇지 않으면 릴리스 모드와 충돌하는 디버그 모드에서 올바르게 실행되는 코드가 있습니다.
Michael Burr

1
아니요, 변수는 전혀 초기화되지 않으며 할당 될 때까지 변수를 "사용"하는 것은 여전히 ​​UB입니다. 그러나 기본 메모리 내용은 종종 0x0000000 또는 0xDEADBEEF 또는 기타 인식 가능한 패턴으로 미리 채워집니다.
궤도의 경쾌함 레이스 2011 년

26

지금까지 릴리스 애플리케이션을 디버깅하는 데 사용할 수있는 기술에 대한 진지한 개요를 제공하려는 답변은 없습니다.

  1. 릴리스 및 디버그 빌드는 여러 가지 이유로 다르게 작동합니다. 다음은 훌륭한 개요입니다. 이러한 각 차이점은 디버그 빌드에 존재하지 않는 릴리스 빌드의 버그를 유발할 수 있습니다.

  2. 디버거가 있으면 릴리스 및 디버그 빌드 모두 에서 프로그램의 동작이 변경 될 수 있습니다 . 이 답변을 참조하십시오. 간단히 말해서, 적어도 Visual Studio 디버거는 프로그램에 연결될 때 자동으로 디버그 힙을 사용합니다. 환경 변수 _NO_DEBUG_HEAP를 사용하여 디버그 힙을 끌 수 있습니다. 컴퓨터 속성 또는 Visual Studio의 프로젝트 설정에서 지정할 수 있습니다. 그러면 연결된 디버거로 충돌을 재현 할 수 있습니다.

    여기에서 힙 손상 디버깅에 대해 자세히 알아보십시오.

  3. 이전 솔루션이 작동하지 않으면 처리되지 않은 예외를 포착 하고 충돌이 발생하는 인스턴스에 사후 디버거를 연결해야 합니다. 예를 들어 WinDbg를 사용하여 사용 가능한 사후 디버거 및 MSDN에서의 설치에 대한 세부 정보 를 사용할 수 있습니다.

  4. 예외 처리 코드를 개선 할 수 있으며 이것이 프로덕션 애플리케이션 인 경우 다음을 수행해야합니다.

    ㅏ. 다음을 사용하여 사용자 지정 종료 처리기를 설치합니다.std::set_terminate

    이 문제를 로컬로 디버깅하려면 종료 처리기 내부에서 무한 루프를 실행하고 일부 텍스트를 콘솔에 출력하여 std::terminate호출되었음을 알릴 수 있습니다 . 그런 다음 디버거를 연결하고 호출 스택을 확인합니다. 또는이 답변에 설명 된대로 스택 추적을 인쇄합니다.

    프로덕션 응용 프로그램에서는 여기에 설명 된대로 문제를 분석 할 수있는 작은 메모리 덤프와 함께 오류 보고서를 집으로 보낼 수 있습니다.

    비. 하드웨어 및 소프트웨어 예외를 모두 포착 할 수있는 Microsoft의 구조적 예외 처리 메커니즘 을 사용합니다. MSDN을 참조하십시오 . SEH를 사용하여 코드의 일부를 보호하고 a)에서와 동일한 접근 방식을 사용하여 문제를 디버깅 할 수 있습니다. SEH는 프로덕션 앱에서 오류 보고서를 보낼 때 사용할 수있는 발생한 예외에 대한 자세한 정보를 제공합니다.


16

주의해야 할 사항 :

배열 오버런-Visual Studio 디버거가 충돌을 중지 할 수있는 패딩을 삽입합니다.

경쟁 조건-여러 스레드가 관련된 경우 경쟁 조건이 많은 경우 응용 프로그램이 직접 실행될 때만 나타납니다.

연결-올바른 라이브러리를 가져 오는 릴리스 빌드입니다.

시도 할 사항 :

Minidump-정말 사용하기 쉬울 것입니다 (msdn에서 찾아보기 만하면됩니다). 각 스레드에 대한 전체 크래시 덤프를 제공합니다. 출력을 Visual Studio에로드하기 만하면 충돌 당시 디버깅중인 것처럼 보입니다.


1
안녕하세요.이 답변에 대해 익명의 반대표를 받았습니다. 이유를 이해하고 싶습니다.
morechilli 2013-08-30

12

WinDbg를 사후 디버거로 설정할 수 있습니다. 그러면 디버거가 시작되고 충돌이 발생할 때 프로세스에 연결됩니다. 사후 디버깅을 위해 WinDbg를 설치하려면 / I 옵션을 사용하십시오 ( 대문자로 표시됨).

windbg /I

자세한 내용은 여기를 참조 하세요 .

원인에 관해서는 다른 답변에서 알 수 있듯이 아마도 단일화 된 변수 일 것입니다.


2
그리고 컴파일러가 릴리스 빌드의 경우에도 PDB 파일을 생성하도록 할 수 있다는 것을 잊지 마십시오. 기본값은 아닙니다.
Michael Burr

정말로 질문에 대한 유일한 답입니다.
Sebastian

10

몇 시간의 디버깅 끝에 마침내 버퍼 오버플로로 인해 발생한 문제의 원인이 단일 바이트 차이를 일으킨다는 것을 발견했습니다.

char *end = static_cast<char*>(attr->data) + attr->dataSize;

이것은 fencepost 오류 (오프 바이 원 오류)이며 다음과 같이 수정되었습니다.

char *end = static_cast<char*>(attr->data) + attr->dataSize - 1;

이상한 점은 내 코드의 여러 부분 주변에 _CrtCheckMemory ()를 여러 번 호출했고, 항상 1을 반환했다는 것입니다. "return false;"를 배치하여 문제의 원인을 찾을 수있었습니다. 테스트 케이스를 호출 한 다음 결국 시행 착오를 통해 오류가 발생한 위치를 결정합니다.

의견을 보내 주셔서 감사합니다. 오늘 windbg.exe에 대해 많은 것을 배웠습니다! :)


8
오늘 나는 비슷한 문제를 디버깅하고 있었고 _CrtCheckMemory ()는 항상 1을 반환했습니다.하지만 그 이유를 깨달았습니다. 릴리스 모드에서 _CrtCheckMemory는 #defined가 ((int) 1)로 정의되었습니다.
Brian Morearty

7

exe를 릴리스 파일로 빌드 했더라도 추적을 스택하고 제한된 양의 변수 검사를 수행 할 수있는 PDB (프로그램 데이터베이스) 파일을 생성 할 수 있습니다. 빌드 설정에는 PDB 파일을 만드는 옵션이 있습니다. 이것을 켜고 다시 연결하십시오. 그런 다음 먼저 IDE에서 실행하여 충돌이 발생하는지 확인하십시오. 그렇다면 좋습니다. 모든 것을 살펴볼 준비가되었습니다. 그렇지 않은 경우 명령 줄에서 실행할 때 다음 두 가지 중 하나를 수행 할 수 있습니다.

  1. EXE를 실행하고 충돌 전에 프로세스에 연결 (Visual Studio의 도구 메뉴)을 수행합니다.
  2. 충돌 후 디버거를 시작하는 옵션을 선택합니다.

PDB 파일을 가리 키도록 요청 받으면 파일을 찾아보십시오. PDB가 EXE 또는 DLL과 동일한 출력 폴더에 있으면 자동으로 선택 될 것입니다.

PDB는 스택 트레이스, 변수 등을 볼 수 있도록 충분한 심볼 정보가있는 소스에 대한 링크를 제공합니다. 값을 정상적으로 검사 할 수 있지만 최적화 단계가 의미 만있을 수 있으므로 잘못된 판독 값을 얻을 수 있습니다. 레지스터에 나타나거나 예상과 다른 순서로 일이 발생합니다.

NB : 여기서는 Windows / Visual Studio 환경을 가정하고 있습니다.


3

이와 같은 충돌은 IDE가 일반적으로 초기화되지 않은 변수의 내용을 0, null 또는 기타 '적당한'값으로 설정하기 때문에 거의 항상 발생하는 반면, 기본적으로 실행하면 시스템이 선택하는 임의의 쓰레기를 얻게됩니다.

따라서 오류는 제대로 초기화되기 전에 포인터를 사용하는 것과 같은 것을 사용하고 있으며 위험한 곳을 가리 키지 않기 때문에 IDE에서 벗어나고 있다는 것입니다. 또는 값은 사용자가 처리합니다. 오류 검사-하지만 릴리스 모드에서는 불쾌한 일을합니다.


3

분석 할 수있는 크래시 덤프를 얻으려면 다음을 수행하십시오.

  1. 코드에 대한 pdb 파일을 생성합니다.
  2. exe 및 dll이 동일한 주소에로드되도록 rebase합니다.
  3. Dr. Watson 과 같은 사후 디버거 사용
  4. crash finder 와 같은 도구를 사용하여 충돌 실패 주소를 확인하십시오 .

Windows 용 디버깅 도구 의 도구도 확인해야합니다 . 애플리케이션을 모니터링하고 두 번째 예외 이전의 모든 첫 번째 예외를 볼 수 있습니다.

도움이 되길 바랍니다 ...


3

이와 같은 오류를 디버깅하는 가장 좋은 방법은 디버그 빌드에 대한 최적화를 활성화하는 것입니다.


2

앱이 당신과 비슷하게 작동했을 때 문제가 발생했습니다. sprintf에서 불쾌한 버퍼 오버런으로 판명되었습니다. 당연히 디버거가 연결된 상태에서 실행할 때 작동했습니다. 내가 한 일은 처리되지 않은 예외 필터 ( SetUnhandledExceptionFilter ) 를 설치하는 것이 었 습니다. 여기서 제한 시간 값이 INFINITE 인 가짜 핸들에서 WaitForSingleObject를 사용하여 무한히 차단했습니다.

따라서 다음과 같이 할 수 있습니다.

long __stdcall MyFilter (EXCEPTION_POINTERS *)
{
    핸들 hEvt = :: CreateEventW (0,1,0,0);
    if (hEvt)
    {
        if (WAIT_FAILED == :: WaitForSingleObject (hEvt, INFINITE))
        {
            // 로그 실패
        }
    }

}
// wmain / WinMain 어딘가에 :
SetUnhandledExceptionFilter (MyFilter);

그런 다음 버그가 나타난 후 디버거를 연결했습니다 (gui 프로그램이 응답을 멈춤).

그런 다음 덤프를 가져와 나중에 작업 할 수 있습니다.

.dump / ma 경로 _ 덤프 _ 파일

또는 즉시 디버그하십시오. 가장 간단한 방법은 런타임 예외 처리 기계가 프로세서 컨텍스트를 저장 한 위치를 추적하는 것입니다.

sd esp 범위 1003f

명령은 검색 길이가 제공되는 CONTEXT 레코드에 대한 스택 주소 공간을 검색합니다. 나는 보통 'l? 10000' 과 같은 것을 사용합니다 . 일반적으로 처리되지 않은 예외 필터 프레임 근처에있는 레코드로 지나치게 큰 숫자를 사용하지 마십시오. 1003f는 프로세서 상태를 캡처하는 데 사용되는 플래그 (CONTEXT_FULL에 해당한다고 생각)의 조합입니다. 검색은 다음과 유사합니다.

0 : 000> sd esp l1000 1003f
0012c160 0001003f 00000000 00000000 00000000? ...............

결과가 반환되면 cxr 명령에 주소를 사용하십시오.

.cxr 0012c160

이렇게하면 충돌시 정확히이 새로운 CONTEXT로 이동합니다 (앱이 충돌 할 때 정확히 스택 추적을 얻습니다). 또한 다음을 사용하십시오.

.exr -1

정확히 어떤 예외가 발생했는지 확인합니다.

도움이되기를 바랍니다.


2

때때로 이것은 "assert"매크로 안에 중요한 작업을 래핑했기 때문에 발생합니다. 아시다시피 "assert"는 디버그 모드에서만 표현식을 평가합니다.


1

진단 정보를 얻는 문제와 관련하여 WinDbg.exe의 대안으로 adplus.vbs를 사용해 보셨습니까? 실행중인 프로세스에 연결하려면

adplus.vbs -crash -p <process_id>

또는 충돌이 빠르게 발생하는 경우 응용 프로그램을 시작하려면 :

adplus.vbs -crash -sc your_app.exe

adplus.vbs에 대한 전체 정보는 http://support.microsoft.com/kb/286350 에서 찾을 수 있습니다 .


1

디버거가 연결된 Ntdll.dll

명령 줄 / 데스크톱에서 프로그램을 시작하는 것과 반대로 IDE 또는 WinDbg에서 프로그램을 시작하는 것의 차이점 중 하나는 디버거가 연결된 상태 (예 : IDE 또는 WinDbg)로 시작할 때 ntdll.dll이 약간의 유효성 검사를 수행하는 다른 힙 구현을 사용한다는 것입니다. 메모리 할당 / 해제에.

ntdll.dll의 예기치 않은 사용자 중단 점에서 일부 관련 정보를 읽을 수 있습니다 . 문제를 식별하는 데 도움이 될 수있는 한 가지 도구는 PageHeap.exe 입니다.

충돌 분석

당신이 겪고있는 "충돌"이 무엇인지 쓰지 않았습니다. 프로그램이 충돌하고 Microsoft에 오류 정보를 보내도록 제안하면 기술 정보를 클릭하고 최소한 예외 코드를 확인할 수 있으며 약간의 노력으로 사후 분석을 수행 할 수도 있습니다 ( Heisenbug 참조). : WinApi 프로그램이 일부 컴퓨터에서 충돌 함) 지침)


1

Vista SP1에는 실제로 시스템에 내장 된 정말 멋진 크래시 덤프 생성기가 있습니다. 안타깝게도 기본적으로 켜져 있지 않습니다!

이 문서를 참조하십시오 : http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx

이 접근 방식의 이점은 영향을받는 시스템에 추가 소프트웨어를 설치할 필요가 없다는 것입니다. 잡아서 찢어, 자기야!


1

제 경험으로는 대부분 메모리 손상 문제입니다.

예 :

char a[8];
memset(&a[0], 0, 16);

: /*use array a doing some thing */

코드를 실행할 때 디버그 모드에서 정상이 될 수 있습니다.

그러나 릴리스에서는 충돌이 될 수 있습니다.

저에게있어서 기억이 한계를 벗어난 곳을 뒤지는 것은 너무 힘들어요.

Visual Leak Detector (windows) 또는 valgrind (linux) 와 같은 일부 도구를 사용하는 것이 더 현명합니다.


1

정답을 많이 보았습니다. 그러나 나를 도운 사람은 없습니다. 제 경우 에는 정렬되지 않은 메모리로 SSE 명령어 를 잘못 사용했습니다 . 수학 라이브러리 (사용하는 경우)를 살펴보고 SIMD 지원을 비활성화하고 충돌을 다시 컴파일 및 재현 해보십시오.

예:

프로젝트에는 mathfu를 하고 STL 벡터 : std :: vector <mathfu :: vec2> 와 함께 클래스를 사용합니다 . 이러한 사용은 STL 기본 할당자가 필요한 16 바이트 정렬을 보장하지 않기 때문에 mathfu :: vec2 항목을 생성 할 때 충돌을 일으킬 수 있습니다 . 이 경우 아이디어를 증명하기 위해 mathfu를#define MATHFU_COMPILE_WITHOUT_SIMD_SUPPORT 1 포함하기 전에 정의 하고 Release 구성에서 다시 컴파일 한 다음 다시 확인할 수 있습니다.

그만큼 디버그RelWithDebInfo 구성은 내 프로젝트에 대해 잘 작동하지만 릴리스 를. 이 동작의 원인은 아마도 디버거가 할당 / 할당 해제 요청을 처리하고 메모리에 대한 액세스를 확인하고 확인하기 위해 일부 메모리 부기 작업을 수행하기 때문일 것입니다.

Visual Studio 2015 및 2017 환경에서 상황을 경험했습니다.


0

비슷한 일이 GCC에서 한 번 나에게 일어났습니다. 개발 프로세스가 아닌 최종 릴리스를 만들 때만 활성화 된 너무 공격적인 최적화로 밝혀졌습니다.

글쎄요, 사실을 말하면 그것은 gcc가 아니라 제 잘못이었습니다. 제 코드가 특정 최적화가 수행되지 않았을 것이라는 사실에 의존하고 있다는 사실을 알아 차리지 못했기 때문입니다.

그것을 추적하는 데 많은 시간이 걸렸고 뉴스 그룹에 질문하고 누군가가 그것에 대해 생각하게 만들었 기 때문에 왔습니다. 그러니 당신에게도 이런 일이 일어날 경우를 대비해 부탁을 드리겠습니다.


0

이 기사 가 귀하의 시나리오에 유용하다는 것을 알았습니다 . ISTR 컴파일러 옵션은 오래되었습니다. Visual Studio 프로젝트 옵션을 살펴보고 릴리스 빌드 등에 대한 pdb 파일을 생성하는 방법을 확인합니다.


0

디버거 내부가 아닌 외부에서 발생할 것으로 의심됩니다. 디버거에서 실행하면 일반적으로 응용 프로그램 동작이 변경되지 않습니다. 콘솔과 IDE 간의 환경 차이를 확인합니다. 또한 최적화없이 디버그 정보를 사용하여 릴리스를 컴파일하고 이것이 동작에 영향을 미치는지 확인하십시오. 마지막으로 다른 사람들이 여기에서 제안한 사후 디버깅 도구를 확인하세요. 일반적으로 여기에서 단서를 얻을 수 있습니다.


0

릴리스 빌드 디버깅은 코드 줄이 실행되는 것처럼 보이는 순서를 변경하는 최적화로 인해 고통 스러울 수 있습니다. 정말 혼란 스러울 수 있습니다!

적어도 문제의 범위를 좁히는 한 가지 기술은 MessageBox ()를 사용하여 코드가 프로그램의 어떤 부분에 도달했는지를 나타내는 빠른 문을 표시하는 것입니다 ( "Starting Foo ()", "Starting Foo2 ()"); 의심되는 코드 영역의 함수 맨 위에 배치하기 시작하십시오 (크래시되었을 때 무엇을하고 있었습니까?). 어떤 함수인지 알 수 있으면 메시지 상자를 코드 블록으로 변경하거나 몇 줄로 좁힐 때까지 해당 함수 내의 개별 줄로 변경합니다. 그런 다음 변수 값 인쇄를 시작하여 충돌 지점에서 어떤 상태인지 확인할 수 있습니다.


그는 이미 printfs를 뿌려 보았으므로 메시지 상자는 파티에 새로운 것을 가져 오지 않습니다.
Greg Whitfield

0

_CrtCheckMemory () 를 사용 하여 할당 된 메모리가 어떤 상태인지 확인하십시오. 모든 것이 잘되면 _CrtCheckMemoryTRUE를 반환 하고 그렇지 않으면 FALSE를 반환 합니다 .


0

전역 플래그를 활성화 한 상태로 소프트웨어를 실행할 수 있습니다 (Windows 용 디버깅 도구 참조). 그것은 종종 문제를 해결하는 데 도움이 될 것입니다.


0

예외가 발생하면 프로그램에서 미니 덤프를 생성 한 다음 디버거 (예 : WinDbg)에서 엽니 다. 살펴볼 주요 기능 : MiniDumpWriteDump, SetUnhandledExceptionFilter


0

누군가가 유익하다고 생각할 수있는 경우가 있습니다. 디버그가 아닌 Qt Creator의 릴리스에서만 충돌했습니다. .ini 파일을 사용하고있었습니다 (다른 드라이브에 복사 할 수있는 앱과 레지스트리가 손상되면 설정이 손실되는 앱을 선호하기 때문). 이는 앱의 디렉토리 트리 아래에 설정을 저장하는 모든 앱에 적용됩니다. 디버그 및 릴리스 빌드가 서로 다른 디렉터리에있는 경우 서로 다른 설정을 가질 수도 있습니다. 다른 하나는 확인되지 않은 선호도를 확인했습니다. 그것은 내 충돌의 원인으로 밝혀졌습니다. 찾은 건 다행이야.

말하기 싫지만 MS Visual Studio Community Edition에서만 충돌을 진단했습니다. VS를 설치 한 후 Qt Creator에서 내 앱이 충돌하도록하고 Visual Studio의 디버거 에서 열도록 선택했습니다 . 내 Qt 앱에는 기호 정보가 없었지만 Qt 라이브러리에는 일부가있는 것으로 나타났습니다. 그것은 나를 불쾌한 선으로 이끌었습니다. 어떤 메서드가 호출되었는지 알 수 있었기 때문입니다. (그래도 Qt는 편리하고 강력하며 크로스 플랫폼 LGPL 프레임 워크라고 생각합니다.)


-3

나는이 오류가 있었고 대 청소하려고 할 때도 충돌했습니다! 내 프로젝트. 그래서 Release 디렉토리에서 obj 파일을 수동으로 삭제 한 후 제대로 빌드되었습니다.


-6

나는 Rolf에 동의합니다. 재현성이 매우 중요하기 때문에 비디 버그 모드가 없어야합니다. 모든 빌드는 디버깅 가능해야합니다. 디버깅 할 두 개의 타겟이 있으면 디버깅 부하가 두 배 이상 증가합니다. 사용할 수없는 경우가 아니면 "디버그 모드"버전을 보내십시오. 이 경우 사용 가능하게 만드십시오.


이것은 10 %의 응용 프로그램에서 작동 할 수 있지만 확실히 모든 응용 프로그램에는 적용되지 않습니다. DEBUG 빌드로 출시 된 게임을 플레이하고 싶습니까? 분해하기 쉬운 모드로 상표가 붙은 비밀 보안 코드를 PDB와 함께 제공 하시겠습니까? 아닐 것 같아요.
steffenj

Steffenj : 게임 개발자가 버그를 찾아 주길 바랍니다. 이상적으로는 배송 전에 배송되지만 이후라면 재생산하고 추적 할 수있는 충분한 정보를 얻을 수 있기를 바랍니다. 비밀 코드 인 경우 상표가 적용되지 않습니다. PDB? 단백질 데이터뱅크? 파이썬 디버거?
wnoise

IMHO, 그건 나쁜 생각입니다. 실행 파일은 더 크고 최적화되지 않았으며 훨씬 느리게 실행됩니다. 이러한 경우는 매우 드뭅니다. 그들이 일어날 때 특히 화가 나더라도. 극히 드문 최악의 경우 디버깅에 대해 걱정하면서 지속적으로 열등한 제품을 제공해서는 안됩니다. (저는 많은 반대표 중 하나가 아니 었습니다.) 저는 NASA를 위해 프로그래밍을했습니다. 최소한 모든 코드 줄은 한 번 테스트해야한다고 말했습니다. 단위 테스트도 도움이 될 수 있습니다.
CodeLurker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.