developer tip

디버그 모드에없는 릴리스 버전의 버그에 대한 일반적인 이유

optionbox 2020. 11. 21. 14:13
반응형

디버그 모드에없는 릴리스 버전의 버그에 대한 일반적인 이유


릴리스 컴파일 모드에서만 나타나고 디버그 모드에서는 발생하지 않는 버그 및 비정상적인 프로그램 동작의 일반적인 이유는 무엇입니까?


많은 경우 C ++의 디버그 모드에서는 모든 변수가 null로 초기화되지만 명시 적으로 언급하지 않는 한 릴리스 모드에서는 동일하지 않습니다.

디버그 매크로 및 초기화되지 않은 변수 확인

프로그램에서 스레딩을 사용하는 경우 최적화는 릴리스 모드에서 몇 가지 문제를 일으킬 수도 있습니다.

또한 모든 예외를 확인하십시오. 예를 들어 릴리스 모드와 직접 관련이 없지만 때때로 VC ++의 mem 액세스 위반과 같은 몇 가지 중요한 예외를 무시하지만 최소한 Linux, Solaris와 같은 다른 OS에서는 동일한 문제가 발생할 수 있습니다. 이상적으로 프로그램은 NULL 포인터에 액세스하는 것과 같은 중요한 예외를 포착하지 않아야합니다.


일반적인 함정은 ASSERT 내부에 부작용이있는 표현식을 사용하는 것입니다.


다른 차이점은 다음과 같습니다.

  • 가비지 수집 언어에서 수집기는 일반적으로 릴리스 모드에서 더 공격적입니다.
  • 메모리 레이아웃은 종종 다를 수 있습니다.
  • 메모리는 다르게 초기화 될 수 있습니다 (예 : 디버그 모드에서 제로화되거나 릴리스에서 더 적극적으로 재사용 될 수 있음).
  • 로컬은 릴리스에서 값을 등록하도록 승격 될 수 있으며 이로 인해 부동 소수점 값에 문제가 발생할 수 있습니다.

나는 과거에 디버그 빌드에서는 괜찮 았지만 릴리스 빌드에서는 크래시되는 많은 버그에 물렸다. 많은 근본적인 원인 (물론이 스레드에 이미 요약 된 원인을 포함하여)이 있으며 다음 모두에 의해 발견되었습니다.

  • 에서 멤버 변수 또는 멤버 함수를 사용 #ifdef _DEBUG하므로 디버그 빌드에서 클래스 크기가 다릅니다. 때때로 #ifndef NDEBUG릴리스 빌드에서 사용됨
  • 비슷하게 #ifdef두 빌드 중 하나에 만 존재 하는 다른 것이 있습니다.
  • 디버그 버전은 시스템 라이브러리의 디버그 버전, 특히 힙 및 메모리 할당 기능을 사용합니다.
  • 릴리스 빌드의 인라인 함수
  • 헤더 파일 포함 순서. 이로 인해 문제가 발생 #pragma pack해서는 안되지만 재설정되지 않은 a와 같은 것이 있으면 불쾌한 문제가 발생할 수 있습니다. 미리 컴파일 된 헤더 및 강제 포함을 사용하여 유사한 문제가 발생할 수도 있습니다.
  • 캐시 : 릴리스 빌드에서만 사용되는 캐시 또는 다른 캐시 크기 제한과 같은 코드가있을 수 있습니다.
  • 프로젝트 구성 : 디버그 및 릴리스 구성은 빌드 설정이 다를 수 있습니다 (IDE를 사용할 때 발생할 수 있음).
  • 디버그 전용 코드의 결과로 발생하는 경쟁 조건, 타이밍 문제 및 기타 부작용

디버그 / 릴리스 버그를 해결하기 위해 수년 동안 축적 한 몇 가지 팁 :

  • 가능한 경우 디버그 빌드에서 비정상적인 동작을 재현하고 더 나은 경우이를 캡처하는 단위 테스트를 작성합니다.
  • 컴파일러 설정, 캐시, 디버그 전용 코드의 차이점에 대해 생각해보십시오. 이러한 차이를 일시적으로 최소화하십시오.
  • 최적화가 꺼진 릴리스 빌드 (디버거에서 유용한 데이터를 얻을 가능성이 더 큼) 또는 최적화 된 디버그 빌드를 만듭니다. 디버그와 릴리스 간의 변경 사항을 최소화하면 어떤 차이가 버그를 유발하는지 격리 할 수 ​​있습니다.

예! 조건부 컴파일이있는 경우 타이밍 버그 (최적화 된 릴리스 코드 대, 최적화되지 않은 디버그 코드), 메모리 재사용 대 디버그 힙이있을 수 있습니다.


특히 C 영역에있는 경우 가능합니다.

한 가지 원인은 DEBUG 버전이 길잃은 포인터를 확인하는 코드를 추가하고 어떻게 든 코드가 충돌하거나 잘못 작동하지 않도록 보호하기 때문일 수 있습니다. 이 경우 컴파일러에서받은 경고 및 기타 메시지를주의 깊게 확인해야합니다.

또 다른 원인은 최적화 (일반적으로 릴리스 버전에서는 켜져 있고 디버그에서는 꺼져 있음) 일 수 있습니다. 코드 및 데이터 레이아웃이 최적화되었을 수 있으며 디버깅 프로그램이 예를 들어 사용되지 않은 메모리에 액세스하는 동안에 만 릴리스 버전이 예약 된 메모리에 액세스하거나 코드를 가리 키려고합니다!

편집 : 다른 사람이 언급 한 것을 보았습니다 : 물론 DEBUG 모드에서 컴파일하지 않으면 조건부로 제외되는 전체 코드 섹션이있을 수 있습니다. 이 경우 프로그램 자체의 정확성에 필수적인 것이 아니라 실제로 코드를 디버깅하기를 바랍니다.


CRT 라이브러리 함수는 디버그 대 릴리스 (/ MD 대 / MDd)에서 다르게 작동합니다.

예를 들어 디버그 버전은 종종 클레임을 확인하기 위해 지정된 길이까지 전달하는 버퍼를 미리 채 웁니다. 예로는 strcpy_s, StringCchCopy, 문자열 이전에 종료 등의 경우에도 szDest는 더 나은 N 바이트 길이!


예를 들어 다음과 같은 구조를 사용하는 경우

#if DEBUG

//some code

#endif

.NET에서 .NET과 같은 조건부 컴파일을 사용하지 않더라도 #if DEBUG컴파일러는 디버그 모드에서보다 릴리스 모드에서 최적화를 통해 훨씬 더 자유롭고 버그만 릴리스 할 수 있습니다.


더 많은 정보를 제공해야하지만 가능합니다. 디버그 버전이 수행하는 작업에 따라 다릅니다. 릴리스 버전으로 컴파일되지 않는 로깅 또는 추가 검사가있을 수 있습니다. 이러한 디버그 전용 코드 경로에는 상태를 변경하거나 이상한 방식으로 변수에 영향을주는 의도하지 않은 부작용이있을 수 있습니다. 디버그 빌드는 일반적으로 느리게 실행되므로 스레딩에 영향을 미치고 경쟁 조건을 숨길 수 있습니다. 릴리스 컴파일에서 곧바로 최적화하는 경우에도 동일하지만, 릴리스 컴파일이 최적화로서 무언가를 단락시킬 수 있습니다 (요즘에는 거의 없을지라도).


Without more details, I will assume that "not OK" means that it either does not compile or throws some sort of error at runtime. Check if you have code that relies on the compilation version, either via #if DEBUG statements or via methods marked with the Conditional attribute.


That is possible, if you have conditional compilation so that the debug code and release code are different, and there is a bug in the code that is only use in the release mode.

Other than that, it's not possible. There are difference in how debug code and release code are compiled, and differences in how code is executed if run under a debugger or not, but if any of those differences cause anything other than a performance difference, the problem was there all along.

In the debug version the error might not be occuring (because the timing or memory allocation is different), but that doesn't mean that the error is not there. There may also be other factors that are not related to the debug mode that changes the timing of the code, causing the error to occur or not, but it all boils down to the fact that if the code was correct, the error would not occur in any of the situations.

So, no, the debug version is not OK just because you can run it without getting an error. If an error occurs when you run it in release mode, it's not because of the release mode, it's because the error was there from the start.


There are compiler optimizations that can break valid code because they are too aggressive.

Try compiling your code with less optimization turned on.


In a non-void function, all execution paths should end with a return statement.

In debug mode, if you forget to end such a path with a return statement then the function usually returns 0 by default.

However, in release mode your function may return garbage values, which may affect how your program runs.


It's possible. If it happens and no conditional compilation is involved, than you can be pretty sure that your program is wrong, and is working in debug mode only because of fortuitous memory initializations or even layout in memory!


I just experienced that when I was calling an assembly function that didn't restored the registers' previous values.

In the "Release" configuration, VS was compiling with /O2 which optimizes the code for speed. Thus some local variables where merely mapping to CPU registers (for optimization) which were shared with the aforementioned function leading to serious memory corruption.

Anyhow see if you aren't indirectly messing with CPU registers anywhere in your code.


I remember while ago when we were building dll and pdb in c/c++.

I remember this:

  • Adding log data would sometime make the bug move or disappear or make a totally other error appears (so it was not really an option).
  • Many of these errors where due to char allocation in strcpy and strcat and arrays of char[] etc...
  • We weeded some out by running bounds checker and simply fixing the memory alloc/dealloc issues.
  • Many times, we systematically went through the code and fixed a char allocation (like through all the files).
  • Definitely it is something related to memory allocation and management and constraints and differences between Debug mode and release mode.

And then hoped for the best.

I sometimes, temporarily delivered debug versions of dlls to clients, in order not to hold off production, while working on these bugs.


Another reasons could be DB calls. Are you saving and updating same record multiple times in same thread, sometimes for updating. Its possible the update failed or didnt work as expected because the previous create command was still processing and for update, the db call failed to find any record. this wont happen in debug as debugger makes sure to complete all pending tasks before landing.

참고URL : https://stackoverflow.com/questions/1762088/common-reasons-for-bugs-in-release-version-not-present-in-debug-mode

반응형