>source

다른 프로그램에서 사용하고있는 유용한 함수를 포함하는 정적 라이브러리 (.a)가 있습니다. 링크가 잘 작동하고 lib의 함수가 발견되지만 프로그램이 실행될 때 제대로 작동하지 않습니다. 반면, 프로그램 코드에 직접 필요한 lib 함수를 복사/붙여 넣을 경우 잘 작동합니다. 게다가, 그것은 win32에서 잘 작동했지만 지금은 Win64에 있습니다.

편집 : 코드가 끔찍하다는 것을 알고 있습니다 (내 것이 아닙니다). 프로그램에서 직접 복사 할 때 작동하므로 개발자가 변경하지 않습니다. 내가 필요한 것은 함수가있는 라이브러리를 링크 할 때, Linux64 및 Win32에서 완벽하게 작동 할 때 왜 제대로 작동하지 않는지를 이해하는 것입니다. 이 코드에서 많은 문제를 발견 할 수 있지만 이는 단지 하나의 예일뿐입니다. 왜 프로그램에서 작동하지만 lib로 연결되지 않은지 설명하지 않기 때문에 개발자가 전혀 신경 쓰지 않기 때문에 나에게 쓸모가 없습니다.

다음은 lib의 문제가있는 함수 중 하나입니다 (lib에 의존하지는 않지만 가장 단순하지만 다른 사람들이 예상대로 작동하지 않는 것으로 의심됩니다).

#if defined(mingwx64)
typedef long long         I64;
#else
typedef long              I64;
#endif
typedef unsigned char     UI8;
void readParamFile (char* filename, UI8* *Params, I64 *ParamsLen){
    FILE* fic;
    char* buf; int buf_Len;
    *Params=NULL; *ParamsLen=0;
    if(!(fic=fopen(filename, "rb"))){
        fprintf(stderr, "Error, can't open %s\n", filename);
        exit (-1);
    }
    fseek(fic, 0, SEEK_END);
    buf_Len=ftell(fic);
    fseek(fic, 0, SEEK_SET);
    if(!(buf=(char*)PtrAlloc(sizeof(char)*buf_Len))){
        fprintf(stderr, "Error: Can't allocate %d bytes", buf_Len);
        exit(-1);
    }
//the files are specifics, i read the lines until the first one which doesn't start with #
    do{
       if(!fgets(buf, buf_Len, fic)){
          fprintf(stderr,"Error: Can't read parameters");
          exit(-1);
       }
       buf[strlen(buf)-1]='\0';
    } while (buf[0]=='#');
    if(!(*Params= (UI8*)PtrAlloc(sizeof(UI8)*strlen(buf)))){
        fprintf(stderr,"Error: can't allocate %d butes", buf_Len);
        exit(-1);
    }
    strncpy((char*) *Params , buf, *ParamsLen=strlen(buf));
    PtrFree(buf);
    fclose(fic);
}

이 함수는 MyLib.a에 있습니다. Mingw64 (Win32에서 Mingw를 사용한 것처럼)를 사용하여 Win64에서 컴파일하면 컴파일이 작동합니다. 그런 다음 MyProg를 컴파일 할 때이 lib를 연결합니다. 컴파일은 잘 진행됩니다. 그리고 MyProg를 시작하면 어느 시점 에서이 기능을 사용하고 strncpy 에서 멈출 것입니다   ( memcpy 이전  사용되었지만 더 좋지 않았습니다). 오류 메시지가 표시되지 않습니다. 아무것도 기다리지 않고 마치 모든 것이 잘 된 것처럼 프로그램이 멈 춥니 다. 이 strncpy 후에 인쇄하려고하면 , 그것은 결코 진행되지 않지만 프로그램은 "정상적으로"끝납니다 (내가 볼 수있는 충돌 없음).

이상한 점은 MyProg 코드 안에이 함수를 복사/붙여 넣기하면 readFileBis 라고하겠습니다. 그런 다음 readFileBis  잘 작동합니다.

그러나 p : 필요한 모든 프로그램 내에서 lib의 모든 기능을 복사/붙여 넣지 않을 것입니다. 낭비가 될 것입니다.

EDIT : 재현 가능한 예제를 만들려고했지만 여전히 노력하고 있습니다. 이 파일이 MyProg의 유일한 파일이라고 가정 해 보겠습니다.

MyProg.c

#define FILENAME "MyDir/ParamFile.txt"
void readParamFileBis (char* filename, UI8* *Params, I64 *ParamsLen){
    //the exact same thing as in readFile, don't wanna make the question too long.
}
int main(int argc, char *argv[]){
    UI8 *Params = NULL; 
    I64 ParamsLen = 0;
//this is working:
    readParamFileBis (FILENAME, &Params, &ParamsLen);
//this is not working : 
    readParamFile (FILENAME, &Params, &ParamsLen);
    exit(0);
}

그리고 ParamFile.txt는 다음과 같이 보입니다 (숫자가 길수록) :

# Introduction text
000500000000064F1B58372A27

여기서 무엇이 잘못되었는지 알고 싶습니다. Win32에서 잘 작동한다는 것을 알고 64 비트와 관련이 있다고 생각하지만 무엇을 모르겠습니다. win64에서 lib와 prog를 모두 다시 컴파일 했으므로 괜찮습니다. 나는 무슨 일이 일어나고 있는지 전혀 모른다.

아, 그와 관련이있을 수도 있고 없을 수도있는 또 다른 이상한 일이 있습니다. 컴파일 할 때 -D ${ARCHI} 플래그를 사용할 수 있습니다. Win32에서 ARCHI는 mnigw386 였습니다. ;win64에서는 mingwx64 입니다. . Win64에서이 플래그를 사용하여 컴파일 할 때 win32에 없었던 인쇄 형식 (예 : % ld를 사용하여 일부 I64를 인쇄하고 마음에 들지 않음)에 대한 경고가 표시됩니다.

편집/솔루션 :문제는 실제로 I64입니다. 나는 int64_t 에 의해 그것을 변경 관리  그리고 그것은 작동하고 있습니다. 또한 Makefiles (250 줄과 16 대상에서 90 줄과 5 대상까지)의 글꼴을 변경 한 다음 아키텍처가 실제로 정의되었지만 컴파일 플래그에는 포함되지 않음을 알았습니다. 그래서 나는 그 프로그램이 그 I64 를 볼 수 없었을 것 같아   long long 로 정의되었다  ( if mingwx64 에 있기 때문에 )가 long 라고 생각했습니다. 그리고 그것은 큰 문제였습니다.

  • 답변 # 1

    게시 된 코드 조각에는 여러 가지 문제가 있습니다 :

    #define FILENAME "MyDir\ParamFile.txt"  부정확하다. #define FILENAME "MyDir\\ParamFile.txt" 로 백 슬래시를 피해야합니다.  또는 모든 Windows 버전에서 작동하는 일반 슬래시를 사용하십시오. #define FILENAME "MyDir/ParamFile.txt"

    I64 유형의 임의 정의  위험하다. <stdint.h> 를 포함시켜야합니다   typedef uint64_t I64; 를 사용하십시오.

    함수 프로토 타입 void readFile(char* filename, UI8 *Params, I64 *ParamsLen)  예상 API와 일치하지 않습니다 : readFile  파일 내용을 읽고 길이 *ParamsLen 의 할당 된 버퍼에 대한 포인터를 저장합니다.   *Params 로 . 프로토 타입은 다음과 같아야합니다.

    int readFile(const char *filename, UI8 **Params, I64 *ParamsLen);
    
    

    readFile  파일을 열거 나 읽을 수없는 경우 오류 코드를 반환해야합니다.

    } 가 누락되었습니다  Wyzwyz 후  기능 exit (-1); 에서 .

    파일에 줄 바꿈으로 끝나지 않은 한 줄이 파일에 들어있는 경우를 대비하여 임시 버퍼는 여분의 바이트로 할당해야합니다.

    readFile  반드시 fgets() 를 저장하지는 않습니다  특히 파일에 파일이없는 경우 배열의 끝에 무조건 마지막 문자를 제거하는 것이 잘못되었습니다.

    '\n' 를 사용하지 않는 이유  휴대용이 아닌 Windows 전용 malloc() 대신 .

    파일 내용을 C 문자열로 사용하려면 null 종결 자에 여분의 바이트를 할당하고 배열 끝에 저장해야합니다.

    이 함수는 뒤틀린 접근 방식을 사용하여 파일에서 행을 읽습니다. 당신은 그것이 무엇을 이해하고 위의 말에서 고치도록 더 열심히 노력해야합니다. C는 예리하고 용서할 수없는 언어로, 사용 된 요소를 잘 이해하지 못하고 프로그래밍하면 버그와 오류가 최대로 발생합니다.

    이 코드와 관련된 주요 문제는 PtrAlloc() 유형의 정의입니다. . I64 를 가정 한 비 휴대용 Win32 코드의 압도적 인 양으로 인해  정확히 32 비트가되도록 Microsoft는 long 를 유지하기로 결정했습니다.  Win64의 32 비트 및 C 라이브러리의 표준 64 비트 유형에 대한 지원 지연 문제로 인해 long  이식성이없는 Microsoft Windows 기본 라이브러리 이것은 %lld 의 일관성을 검사하는 gcc 컴파일러에서 얻는 경고에 대해 설명합니다.  형식 문자열이있는 인수 win32 버전에서작동하면 64 비트 값을 사용하지 않았을 가능성이 있습니다 ( printf ). )입니다.

    정적 라이브러리와 프로그램에 함수 코드를 포함시키는 것의 다른 동작에 대한 가능한 설명은 다른 컴파일러, 컴파일러 옵션 또는 명령 줄 정의를 사용하는 것입니다. 이거 다 확인 했어? 라이브러리를 직접 컴파일하거나 다른 팀에서 바이너리 형식으로 가져 옵니까?

    32 비트와 64 비트 아키텍쳐 사이의 포팅 소프트웨어는 특히 중요하지 않습니다. 특히 이식성이없는 구성을 권장하고 비정상적인 C99를 지원하는 Windows 플랫폼에서는 더욱 그렇습니다.

    코드가 잘못 작성되었을뿐만 아니라 함수의 프로토 타입이 잘못되었습니다 : long long   Params 가 아닙니다  그것은 UI8 * 해야합니다 기능기능은 우연히 작동하며 쉽게 중단됩니다.개발자가 이에 대해 아무 것도 변경하지 않으면 몇 가지 가능한 해결책을 제안합니다.

    함수를 로컬로 복사하고 문제를 해결하며 가짜 라이브러리를 사용하지 마십시오.

    나만의 기능을 작성하십시오.

    다른 회사에서 더 나은 직업을 찾으십시오. 당신은 그곳에서 시간을 낭비하고 있으며, 더 안전한 환경에서 훨씬 더 많은 것을 배울 것입니다.

    UI8 **

  • 이전 java - 연결된 목록에서 키가 주어진 노드를 삭제하십시오
  • 다음 Microsoft Teams에서 임시 그룹 채팅을 만들 때 채팅 기록 표시 안 함