2017-11-11 16 views
0

요약 : 내 컴파일러 설정이어떤 컴파일러/링커 옵션은 구조체가 메모리에 배치하는 방법에 영향을 미칠 수

자세한 사항은 메모리에 설치 얼마나 stucts 변경 될지 알아 내려고 노력하고 있어요 : 나는 동일한 라이브러리 파일 (libgbm.so)의 두 가지 버전을 가지고 있는데, 하나는 사전 빌드 된 바이너리로, 다른 하나는 내 컴퓨터에서 컴파일 된 것이다. 하나는 올바르게 작동하고 하나는 세분화 오류를 발생시킵니다. 내 컴파일러가 미리 컴파일 된 버전과 다른 방식으로 데이터 구조를 전달하는 것 같습니다.

나는 트림 다운 된 버전의 코드를 제공합니다 (하단의 관련 구조 참조). 기본적으로 공유 라이브러리를로드하고 create_device() 함수를 호출합니다. 함수 포인터가있는 데이터 구조 (gbm_device)를 반환합니다.

gbm_create_device(int fd) 
{ 
    struct gbm_device *gbm = NULL; 
    void *module; 
    const struct gbm_backend *backend = NULL 

    module = dlopen("/usr/lib/gbm/gbm_pvr.so", RTLD_NOW | RTLD_GLOBAL); 
    backend = dlsym(module, "gbm_backend"); 
    gbm = backend->create_device(fd); 

    gbm->surface_create(gbm, width, height, format, flags); 
} 

코드가 다르게 실행되는 곳입니다. 미리 컴파일 된 라이브러리를 사용하는 경우, GDB 내 로컬 컴파일 된 버전을 사용하는 경우 gbm->surface_create

0xb6beb5d0 in ??() from /usr/lib/gbm/gbm_pvr.so 

로 후 다음 단계는, GDB는

0xb6c414a4 in ??() from /usr/lib/gbm/gbm_pvr.so 

으로 다음 단계 내가 디버그 기호가없는 음료수 gbm_pvr.so (독점 라이브러리)에 대해서는이 코드가 분명히 두 개의 다른 기능을 수행하고 있습니다 (적어도 메모리 주소의 마지막 3 자리는 동일해야 함).

내가 생각할 수있는 유일한 점은 어떤 컴파일러/링커 설정이 누락 된 것인가라는 것인데, gbm_device 구조가 메모리에 어떻게 배치되어 있는지를 놓친 것이므로 모든 포인터를 엉망으로 만든다.


다음은 준 구조체

struct gbm_device { 
    /* Hack to make a gbm_device detectable by its first element. */ 
    struct gbm_device *(*dummy)(int); 

    int fd; 
    const char *name; 
    unsigned int refcount; 
    struct stat stat; 

    void (*destroy)(struct gbm_device *gbm); 
    int (*is_format_supported)(struct gbm_device *gbm, 
           uint32_t format, 
           uint32_t usage); 

    struct gbm_bo *(*bo_create)(struct gbm_device *gbm, 
           uint32_t width, uint32_t height, 
           uint32_t format, 
           uint32_t usage); 
    struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type, 
           void *buffer, uint32_t usage); 
    int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data); 
    int (*bo_get_fd)(struct gbm_bo *bo); 
    void (*bo_destroy)(struct gbm_bo *bo); 

    struct gbm_surface *(*surface_create)(struct gbm_device *gbm, 
             uint32_t width, uint32_t height, 
             uint32_t format, uint32_t flags); 
    struct gbm_bo *(*surface_lock_front_buffer)(struct gbm_surface *surface); 
    void (*surface_release_buffer)(struct gbm_surface *surface, 
            struct gbm_bo *bo); 
    int (*surface_has_free_buffers)(struct gbm_surface *surface); 
    void (*surface_destroy)(struct gbm_surface *surface); 
}; 

그리고

struct gbm_backend { 
    const char *backend_name; 
    struct gbm_device *(*create_device)(int fd); 
}; 

답변

0

문제를 발견했습니다.

내 빌드 환경에 다음 컴파일러 플래그가 자동으로 추가되었습니다. 이 문제를 해결하면 문제가 해결됩니다.

-D_LARGEFILE_SOURCE 
-D_LARGEFILE64_SOURCE 
-D_FILE_OFFSET_BITS=64 
2

페이지가 구조체 레이아웃의 차이의 증거는 내 내가 코드 오프셋의 차이를 생각하지 않을 수 있습니다. 코드 레이아웃은 컴파일러, 어셈블러, 링커 버전 및 최적화 설정의 차이로 인해 쉽게 변경 될 수 있습니다.

공유 객체가 단순히 구조체의 다른 정의를 사용하는 경우 일 수 있습니다. 게시 한 정의를 사용하면 #pragma pack과 같은 것을 사용하여 다른 레이아웃을 만들어야하는데 이는 원인이 될 것 같지 않습니다.

편집 회원이 struct stat에 누락되었습니다. 이것은 _FILE_OFFSET_BITS 값 (예 : ino_toff_t)에 따라 크기가 변경되기 때문에 실제로는 no입니다. 이식 가능한 코드는 공용 헤더 파일에서 이러한 유형 (및 time_t)을 사용해서는 안됩니다.