Programing

C ++에서 세분화 오류 수정

lottogame 2020. 11. 1. 17:13
반응형

C ++에서 세분화 오류 수정


Windows 및 Unix 용 크로스 플랫폼 C ++ 프로그램을 작성 중입니다. 창 쪽에서는 코드가 컴파일되고 문제없이 실행됩니다. Unix 측에서는 컴파일되지만 실행하려고하면 세그멘테이션 오류가 발생합니다. 내 첫 직감은 포인터에 문제가 있다는 것입니다.

세분화 오류 오류를 찾아 수정하는 좋은 방법은 무엇입니까?


  1. 으로 애플리케이션을 컴파일 -g하면 바이너리 파일에 디버그 기호가 있습니다.

  2. gdbgdb 콘솔을 여는 데 사용 합니다.

  3. file콘솔에서 애플리케이션의 바이너리 파일을 사용 하고 전달합니다.

  4. run애플리케이션을 시작하는 데 필요한 모든 인수를 사용 하고 전달합니다.

  5. 세그멘테이션 오류 를 일으키는 조치를 취하십시오 .

  6. 입력 bt에서 gdb의 스택 추적 얻기 위해 콘솔 분할 오류를 .


때로는 충돌 자체가 문제의 실제 원인이 아닌 경우가 있습니다. 아마도 이전 시점에서 메모리가 박살 났지만 손상이 나타나기까지 시간이 걸렸습니다. 확인 Valgrind의 (체크 배열 범위 포함) 포인터 문제에 대한 검사를 많이 가지고있는. 충돌이 발생한 라인뿐만 아니라 문제 가 시작 되는 위치를 알려줍니다 .


문제가 발생하기 전에 가능한 한 피하십시오.

  • 최대한 자주 코드를 컴파일하고 실행하십시오. 결함이있는 부품을 찾는 것이 더 쉬울 것입니다.
  • 저수준 / 오류가 발생하기 쉬운 루틴을 캡슐화하여 메모리로 직접 작업 할 필요가 거의 없도록합니다 (프로그램 모델링에주의).
  • 테스트 스위트를 유지하십시오. 현재 작동중인 항목, 더 이상 작동하지 않는 항목 등에 대한 개요를 확인하면 문제가 어디에 있는지 파악하는 데 도움이됩니다 ( Boost 테스트 는 가능한 해결책이며 직접 사용하지는 않지만 문서는 어떤 종류인지 이해하는 데 도움이 될 수 있습니다. 정보가 표시되어야 함).

디버깅에 적절한 도구를 사용하십시오. Unix에서 :

  • GDB 는 프로그램 충돌 위치를 알려줄 수 있으며 어떤 컨텍스트에서 볼 수 있도록합니다.
  • Valgrind 는 많은 메모리 관련 오류를 감지하는 데 도움이됩니다.
  • GCC를 사용하면 mudflap 을 사용할 수도 있습니다 . GCC 및 Clang을 사용하면 Address / Memory Sanitizer를 사용할 수 있습니다 . Valgrind가 감지하지 못하는 오류를 감지 할 수 있으며 성능 손실이 더 적습니다.

마지막으로 평소의 것을 추천합니다. 프로그램이 더 읽기 쉽고, 유지 보수가 가능하며, 명확하고 깔끔할수록 디버깅이 가장 쉽습니다.


Unix에서는 valgrind를 사용하여 문제를 찾을 수 있습니다. 무료이며 강력합니다. 직접 수행하려는 경우 new 및 delete 연산자를 오버로드하여 0xDEADBEEF각 새 개체의 전후에 1 바이트가있는 구성을 설정할 수 있습니다 . 그런 다음 각 반복에서 일어나는 일을 추적하십시오. 이것은 모든 것을 잡는 데 실패 할 수 있지만 (그 바이트를 만질 수도 있다는 보장은 없습니다) 과거에는 Windows 플랫폼에서 저에게 효과적이었습니다.


예, 포인터에 문제가 있습니다. 제대로 초기화되지 않은 것을 사용하고있을 가능성이 높지만, 이중 해제 등으로 메모리 관리를 엉망으로 만들 수도 있습니다.

초기화되지 않은 포인터를 지역 변수로 사용하지 않으려면 의미있는 값으로 초기화 할 수있을 때 가능한 한 늦게 (항상 가능한 것은 아님) 선언 해보십시오. 코드를 검사하여 사용하기 전에 가치가 있다는 것을 확신하십시오. 그것에 어려움이 있다면 널 포인터 상수 (보통 NULL또는로 작성 됨 0) 로 초기화 하고 확인하십시오.

초기화되지 않은 포인터를 멤버 값으로 사용하지 않으려면 생성자에서 올바르게 초기화되고 복사 생성자 및 할당 연산자에서 올바르게 처리되는지 확인하십시오. init다른 초기화를 할 수 있지만 메모리 관리를 위해 함수에 의존하지 마십시오 .

클래스에 복사 생성자 또는 할당 연산자가 필요하지 않은 경우이를 전용 멤버 함수로 선언하고 정의하지 않을 수 있습니다. 명시 적으로 또는 암시 적으로 사용되는 경우 컴파일러 오류가 발생합니다.

해당되는 경우 스마트 포인터를 사용하십시오. 여기서 가장 큰 장점은 그것들을 고수하고 일관되게 사용하면 쓰기를 완전히 피할 수 delete있고 아무것도 이중 삭제되지 않는다는 것입니다.

가능하면 C 스타일의 문자열과 배열 대신 C ++ 문자열과 컨테이너 클래스를 사용하십시오. 경계 검사를 강제 할 수 있으므로 .at(i)보다는을 사용하는 것이 좋습니다 [i]. [i]적어도 디버그 모드에서에서 경계를 확인하도록 컴파일러 또는 라이브러리를 설정할 수 있는지 확인하십시오 . 세그먼트 오류는 완벽하게 좋은 포인터에 가비지를 쓰는 버퍼 오버런으로 인해 발생할 수 있습니다.

이러한 작업을 수행하면 세분화 오류 및 기타 메모리 문제의 가능성이 상당히 줄어 듭니다. 의심 할 여지없이 모든 것을 고치는 데 실패 할 것입니다. 그래서 문제가 없을 때 valgrind를 사용하고 문제가 없을 때 valgrind와 gdb를 사용해야합니다.


나는 이와 같은 것을 고치는 데 사용할 방법론을 모릅니다. 나는 당신의 프로그램의 행동이 정의되지 않았다는 바로 그 문제 때문에 하나를 생각해내는 것이 가능하지 않을 것이라고 생각합니다 (SEGFAULT가 일종의 UB에 의해 발생하지 않은 경우는 모릅니다) .

문제가 발생하기 전에 피할 수있는 모든 종류의 "방법론"이 있습니다. 한 가지 중요한 것은 RAII입니다.

그 외에도 최고의 심령 에너지를 던져야합니다.

참고 URL : https://stackoverflow.com/questions/3718998/fixing-segmentation-faults-in-c

반응형