2011-08-13 3 views
2

작은 코드 조각에 문제가 있습니다.이 코드를 별도의 파일에 가지고 있으면 이진 파일을 읽으려고합니다. 그것을 실행하면 파일을 완벽하게 읽습니다.하지만 함수 내의 더 큰 프로젝트에 동일한 코드를 넣으면 항상 2 개의 테스트에서 동일한 파일이됩니다.이상한 행동 : 다른 위치에 같은 코드가 있습니다. 하나는 이진 파일을 읽지 못합니다.

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

int main(int argc, char* argv[]) { 
    char* filename = (char*)"file.binary"; 
    FILE* file = fopen(filename, "rb"); 

    if (!file) { 
     printf("Unable to open %s for reading. \n", filename); 
     fclose(file); 
     free(filename); 
     exit(1); 
    } 

    fseek (file , 0 , SEEK_END); 
    long size = ftell (file); 
    rewind (file); 

    printf("Number of bytes in the file is %ld \n", size); 

    int version = 0; 

    char* string = (char*)malloc(sizeof(char) * 3); 
    fread(string, sizeof(char), 3, file); 

    if (strcmp(string, (char*)"str")) { 
     printf("%s is not properly formatted. \n", filename); 
     fclose(file); 
     free(filename); 
     exit(1); 
    } 

    fread(&version, sizeof(int), 1, file); 

    printf("%s version %d\n", string, version); 

    free(filename); 
    fclose(file); 
} 

그것은 클래스의 기능을 대신 내에서 이동하기 때문에 제외하고 정확히 (붙여 넣기 복사) 같은이기 때문에 더 큰 프로젝트에 코드를 게시하고 있지 않다 :

는 별도의 프로젝트에 코드입니다 주요 기능에 직접. 그것은 꽤 간단한 코드입니다. 그러나 어떤 이상한 이유 때문에 그것은 실패하고 있습니다. 나는 그 주위에서 머리를 쓸 수 없습니다. 두 경우 모두 파일 크기가 올바르게 읽혀 지므로 별도의 프로젝트에서 "문자열"및 "버전"데이터를 올바르게 읽고 올바르게 인쇄하지만 더 큰 프로젝트에서는 문자열이 그렇지 않기 때문에 항상 두 번째 조건부로 들어갑니다. 기대되는 것.

필자는 관련이 있다고 생각하지 않지만 더 큰 프로젝트는 나중에 메인 프로그램에서 링크하는 데 사용되는 정적 라이브러리에 내장됩니다.

실마리가있는 사람이 있습니까? 감사.

+2

모든 캐스팅 매니아는 무엇입니까? 'const char * filename = "file.binary";'에 대해'char * filename = (char *) "file.binary";'를 교환하고'malloc()'의 결과를 캐스팅하지 마십시오. 마지막으로,'string'에 대해서 불편하게 느껴지는 것은 3 바이트를 0으로 끝내지 않고 4 바이트 문자열과 비교하는 것입니다. –

+0

OP에서 "클래스 함수"에 대해 언급 했으므로 큰 프로그램의 컨텍스트는 C가 아니라 C++입니다. –

+0

예, 큰 프로그램의 컨텍스트는 C++입니다. g ++이 void * 및 char *에 대해 징징 대고 있기 때문에 캐스팅이 동일합니다. 데이터 타입에 const char *를 사용하는 경우 파일 이름이 수정되기 때문에 큰 프로젝트에서는 실제로 옵션이 아닙니다. – uorbe001

답변

4

3 개의 문자로 메모리를 할당하지만 "str"과 null 바이트를 비교합니다. 4 바이트를 할당하고 마지막 바이트를 0으로 설정해야합니다 (또는 단순히 calloc을 사용하십시오). 필자는 독립형 애플리케이션에서는 4 번째 바이트가 실제로 0이지만, 더 큰 프로젝트에서는 0이 될 것이라고 상상할 수 있습니다.

+0

이것은 큰 프로젝트에서 4 번째 바이트가 엉망 이었지만 별개의 것으로는 잘 작동하기 때문에주의하지 않았습니다. 나는 널 종료에 더주의해야한다 : - /. 고맙습니다 :-). – uorbe001

+1

strncmp 함수를 사용하여 \ 0 문제를 피할 수도 있습니다. "다른 위치"에 대한 응답으로 여러 유형의 아키텍처 (x86 대 PowerPC, SPARC, ...)에서 컴파일하는 경우 정수 값이 올바르게 읽히지 않으면 리틀 엔디안 문제와 큰 문제가 발생할 수 있습니다. – Gilbert

+0

strncmp를 알지 못했지만, 힌트를 주셔서 감사합니다. 상황에 따라 유용 할 수도 있습니다.하지만 이러한 상황에서는 null *을 사용하는 경우 더 안전 해 보입니다. endianess는 모든 대상 아키텍처가 거의 endian을 사용하지 않기 때문에 지금은 문제가되지 않지만, 이제는이 코드가 big endian 아키텍처에서 사용되고 향후 확장이 필요한 경우에 주석을 추가 할 가치가 있습니다. – uorbe001