2011-08-30 5 views
2

널 포인터를 역 참조하는 것과 같은 seg 결함의 일반적인 원인을 제거하려고 시도했지만, 나는 혼란 스럽다. 이 오류는 테스트 모드의 디버그 모드에서는 나타나지 않지만 컴파일이 진행되는 제작 시스템에는 나타납니다. 가능성을 없애기 위해 둘 다/O0으로 설정됩니다. 문자열 지정을 주석 처리하면 seg 오류가 사라지고 이제는 상황을 이해해야 문제를 해결할 수 있습니다.문자열 할당이 세그멘테이션 오류를 일으키는 이유는 무엇입니까?

더 명확한 부분이있을 수 있지만이 코드는 커널 모드 응용 프로그램에서 호출된다는 추가 복잡성이 있으며 시스템의 안전한 코드 작성에 대한 공급 업체의 지침은 "필요한 모든 기능 운영체제의 어떤 것이라도 또는 OS의 어떤 것도 기다리지 않아도된다 "(축 어적).

union { 
    REAL_T real[8]; 
    char byte[64]; 
} fileName; 

void transferFilenames() { 
    string tempname; 

    // This is from an api I must use, it retrieves values from NVRAM on 
    // an accessory board. Specifically it will return 8 REAL_T values 
    // and store them starting at &filename.real[0], inp/outpArray are 
    // globals defined elsewhere. 
    inpArray.I7_ARRAY.INDEX = 2903; 
    inpArray.I7_ARRAY.LEN = 8; 
    inpArray.I7_ARRAY.Z_PAR_PTR = &fileName.real[0]; 
    b_array (READ_CYCLE_PARAMS, &status, &inpArray, &outpArray); 

    // if status != 0, there was an error 
    if (status == 0) { 
     // there is no guarantee of being null terminated 
     fileName.byte[63] = 0; 

     /* This test code didn't fix the problem 
     int i; 
     char myStr[64]; 
     for (i = 0; i < 64; i++) 
      myStr[i] = fileName.byte[i]; 
     if (myStr[0] != '\0') 
      string mystring(myStr); // seg fault 
     */ 
     tempname.assign(fileName.byte); // Throws seg fault 
     // tempname.assign(&fileName.byte[0]); // try to be more explicit 

     // controlBlock is a global class defined elsewhere 
     controlBlock->setFileName (tempname, ISINPUT); 
    } else { 
     controlBlock->setFileName("BAD", ISINPUT); 
    } 
    return; 
} 

나는 숯불 * 직접 controlBlock->setFileName(&fileName.byte[0])을 내 제어 블록 과부하 및 전부 세그먼트 오류가 사라 문자열 할당을 제거합니다. 모든 오버로드는 char *을 로컬 문자열에 할당하고 일반 메서드를 호출합니다.

나는 무엇을 놓치고 있습니까?

+0

핵심 파일/디버거에서 충돌이 발생할 때'fileName.byte '는 무엇이라고 말합니까? –

+0

@ MarkB 프로그램이 충돌 할 때 생성 된 덤프 파일이 없습니다. 실시간 시스템은 실시간 디버깅을 지원하지 않으며 편안한 타이밍 시스템은이 버그를 나타내지 않습니다. – Stephen

+0

이전에 assign 문과 segfault가 유지되는 것을 제외하고이 블록의 모든 코드를 주석 처리했습니다. 그 반대와 할당 만 남긴 코멘트는 segfault를 제거했습니다. – Stephen

답변

3

tempname.assign()으로 전화가 연결되지 않았을 수 있습니다. 파이프 라이닝은 악마가 실제로 어디에 있는지에 대한 잘못된보고를 초래할 수 있습니다. 이 문장은 나를 악마는 다른 곳에있다 생각한다 : 나는 * 직접 controlBlock-> setFileName (& fileName.byte [0]), 제거 문자열 할당을 모두 분할 숯불을 내 제어 블록을 오버로드

잘못이 사라졌습니다.

당신은 하나의 경우, 다른의 char*setFileNamestd::string을 전달하고 있습니다. 또한, 기간 std::string를 이용하여 할 수있다

controlBlock->setFileName (tempname.c_str(), ISINPUT); 

부록
문제를

controlBlock->setFileName (tempname, ISINPUT); 

를 교체한다. std::string::assign()은 예약 된 크기가 너무 작 으면 malloc으로 호출합니다. 예약 된 크기를 충분히 크게 만드는 것은 작동하지 않을 수도 있습니다. 이것은 단지 malloc 호출을 생성자로 푸시 할 수 있습니다. 동적으로 메모리를 할당하는 것을 사용하면 절대로 절을 따르지 않습니다. 운영 체제에서 아무것도 필요하지 않거나 OS에서 아무것도 기다리지 않아도되는 함수는 작동하지 않습니다..

실제로이 절은이 컴퓨터에서 C++ 라이브러리의 거대한 덩어리를 사용하는 것을 배제 할 수 있습니다. C++ 라이브러리는 메모리 할당 및 할당 해제와 관련하여 매우 느슨하며 std::string은 많은 작업을 수행합니다.

+0

tempname.c_str()을 사용하면 여전히 segfault가 발생했습니다. – Stephen

+0

나는 또한 문제가 assign()에 있지 않을 수도 있다는 데 동의하지만 버그를 재현하기 위해 범위를 좁힐 수있는 유일한 코드 줄입니다. – Stephen

+0

귀하의 의견을 다른 곳에서 받으면 타이밍 버그가 있습니까? 'b_array '가 끝날 때까지 기다려야합니까? 조심해야 할 또 다른 점은 조합의 한 구성원을 설정하고 다른 구성원을 액세스하는 것은 엄밀히 말하면 불법입니다 (정의되지 않은 동작). 이 트릭은 대부분의 컴퓨터와 대부분의 컴파일러에서 작동하지만 항상 그렇지 않은 이상한 짐승이 하나 있습니다. 아마도 당신은 꼬리에 의해 그러한 짐승을 잡았을 것입니다. –

관련 문제