2016-11-15 11 views
0

float32 값을 int32로 다시 작성하는 함수가 있으며 마지막으로 float32가 읽을 때까지 작동합니다. float가 배열의 마지막 값이 아니더라도 (예 : FOR 루프를 일찍 중지하도록 설정 한 경우에도) 배열 외부에서 읽으려는 것처럼 잘못된 읽기가 반환됩니다.배열을 재 배열하면 마지막 값은 항상 잘못된 읽기 예외를 발생시킵니다.

int* roiData = MallocAndCheck(sizeof(int) * roi->dim[1] * roi->dim[2] * roi->dim[3], 1); 

roiData가 무효 roi-> 데이터로부터 촬영 된 INT 값 (보유하는 것을 의미한다 새로운 배열 *

int i, nvoxels; 
nvoxels = roi->dim[1] * roi->dim[2] * roi->dim[3]; 
for (i = 0; i<nvoxels; i++) { 
    roiData[i] = (int)round(((double *)(roi->data))[i]); //line 400 
} 

roidata은 같이 참 -_- 기능 밖에 정의 그것에 포인터 값의 무리와 함께). 위에서 우리는 roi -> 데이터에서 double *을 취하여 값을 반올림 한 다음이를 roiData에 저장하기위한 int로 캐스팅합니다. 오류가 외부 roi-> data (1,048,576 값을 가지고 있어야하며 1,048,576 값을 처리해야 함)를 명시 적으로 읽는 것과 관련이 없다는 것을 여러 번 확인했습니다. 그러나 멈추라 고 말하면 오류가 계속 발생합니다. 20,000 개의 값. 에 대한 반환 코드 0/1 이외에는 다른 코드가 없습니다.

(MallocAndCheck는 malloc, 널 포인터 검사 및 포인터 등록을 함께 랩핑하여 종료시 쉽게 정리할 수있는 사용자 정의 메모리 함수로, 제대로 작동한다고 가정 할 수 있습니다.) 프로토 타입은 MallocAndCheck (int size, int shouldRegister) (등록해야 할 곳은 종료시 정리를 위해 포인터를 추적해야하는지 여부입니다. 또는 수동으로 정리를 처리합니다).

==13348== Invalid read of size 8 
==13348== at 0x402293: nii_recast_to_int32 (pow_filter.c:400) 
==13348== by 0x402293: RecastRoi (pow_filter.c:313) 
==13348== by 0x401450: main (pow_filter.c:50) 
==13348== Address 0x5a03040 is 0 bytes after a block of size 4,194,304 alloc'd 
==13348== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==13348== by 0x4109F9: nifti_image_load (nifti1_io.c:4547) 
==13348== by 0x417CF7: nifti_image_read (nifti1_io.c:3904) 
==13348== by 0x401EBF: OpenNiftiImageFile (pow_filter.c:271) 
==13348== by 0x4013EA: main (pow_filter.c:46) 

이 경우에만 배열에서 아무리 중지해도 마지막으로 읽은 데이터가 트리거됩니다. (roi는 "nifti"함수에 의해 반환 된 포인터입니다).

편집 : 추가 정보 :

투자 수익 (ROI)는 다음과 같이 정의됩니다 : 당신이 nifti_image- 볼 수

typedef struct {    /*!< Image storage struct **/ 

    int ndim ;     /*!< last dimension greater than 1 (1..7) */ 
    int nx ;      /*!< dimensions of grid array 0   */ 
    int ny ;      /*!< dimensions of grid array 1   */ 
    int nz ;      /*!< dimensions of grid array 2   */ 
    int nt ;      /*!< dimensions of grid array 3   */ 
    int nu ;      /*!< dimensions of grid array 4   */ 
    int nv ;      /*!< dimensions of grid array 5   */ 
    int nw ;      /*!< dimensions of grid array 6   */ 
    int dim[8] ;     /*!< dim[0]=ndim, dim[1]=nx, etc.   */ 
    size_t nvox ;     /*!< number of voxels = nx*ny*nz*...*nw */ 
    int nbyper ;     /*!< bytes per voxel, matches datatype */ 
    int datatype ;    /*!< type of data in voxels: DT_* code */ 

    float dx ;     /*!< grid spacings  */ 
    float dy ;     /*!< grid spacings  */ 
    float dz ;     /*!< grid spacings  */ 
    float dt ;     /*!< grid spacings  */ 
    float du ;     /*!< grid spacings  */ 
    float dv ;     /*!< grid spacings  */ 
    float dw ;     /*!< grid spacings  */ 
    float pixdim[8] ;    /*!< pixdim[1]=dx, etc. */ 

    float scl_slope ;    /*!< scaling parameter - slope  */ 
    float scl_inter ;    /*!< scaling parameter - intercept */ 

    float cal_min ;    /*!< calibration parameter, minimum */ 
    float cal_max ;    /*!< calibration parameter, maximum */ 

    int qform_code ;    /*!< codes for (x,y,z) space meaning */ 
    int sform_code ;    /*!< codes for (x,y,z) space meaning */ 

    int freq_dim ;    /*!< indexes (1,2,3, or 0) for MRI */ 
    int phase_dim ;    /*!< directions in dim[]/pixdim[]  */ 
    int slice_dim ;    /*!< directions in dim[]/pixdim[]  */ 

    int slice_code ;   /*!< code for slice timing pattern */ 
    int slice_start ;   /*!< index for start of slices  */ 
    int slice_end ;   /*!< index for end of slices   */ 
    float slice_duration ;  /*!< time between individual slices */ 

    /*! quaternion transform parameters 
    [when writing a dataset, these are used for qform, NOT qto_xyz] */ 
    float quatern_b , quatern_c , quatern_d , 
    qoffset_x , qoffset_y , qoffset_z , 
    qfac  ; 

    mat44 qto_xyz ;    /*!< qform: transform (i,j,k) to (x,y,z) */ 
    mat44 qto_ijk ;    /*!< qform: transform (x,y,z) to (i,j,k) */ 

    mat44 sto_xyz ;    /*!< sform: transform (i,j,k) to (x,y,z) */ 
    mat44 sto_ijk ;    /*!< sform: transform (x,y,z) to (i,j,k) */ 

    float toffset ;    /*!< time coordinate offset */ 

    int xyz_units ;    /*!< dx,dy,dz units: NIFTI_UNITS_* code */ 
    int time_units ;    /*!< dt  units: NIFTI_UNITS_* code */ 

    int nifti_type ;    /*!< 0==ANALYZE, 1==NIFTI-1 (1 file), 
              2==NIFTI-1 (2 files), 
              3==NIFTI-ASCII (1 file) */ 
    int intent_code ;   /*!< statistic type (or something)  */ 
    float intent_p1 ;    /*!< intent parameters     */ 
    float intent_p2 ;    /*!< intent parameters     */ 
    float intent_p3 ;    /*!< intent parameters     */ 
    char intent_name[16] ;  /*!< optional description of intent data */ 

    char descrip[80] ;   /*!< optional text to describe dataset */ 
    char aux_file[24] ;   /*!< auxiliary filename     */ 

    char *fname ;     /*!< header filename (.hdr or .nii)   */ 
    char *iname ;     /*!< image filename (.img or .nii)   */ 
    int iname_offset ;   /*!< offset into iname where data starts */ 
    int swapsize ;    /*!< swap unit in image data (might be 0) */ 
    int byteorder ;    /*!< byte order on disk (MSB_ or LSB_FIRST) */ 
    void *data ;     /*!< pointer to data: nbyper*nvox bytes  */ 

    int    num_ext ; /*!< number of extensions in ext_list  */ 
    nifti1_extension * ext_list ; /*!< array of extension structs (with data) */ 
    analyze_75_orient_code analyze75_orient; /*!< for old analyze files, orient */ 

} nifti_image ; 

> 데이터는 그 저장된 데이터 유형 nifti_image-입니다> 데이터 타입 무효 *입니다.

내 코드에서 위의 코드도 위의 작업을 수행하는 데이터 형식을 확인합니다.

이 특정 경우 데이터 유형은 float32 여야합니다.

+1

어디서나 정의 된 float32가 표시되지 않습니다. 32 비트 타입이 거의없는 double이 있습니다. valgrind는 4 백만 바이트 만 할당된다고 말하면서 1 백만 배가 일반적으로 800 만 바이트를 차지합니다. 백만 가지 값을 읽을 때 한계를 벗어납니다. 나는 모든 수의 읽기보다 적은 후에 위반이 일어났다는 어떤 증거도 보이지 않는다. 코드 및 관련 valgrind 로그와 같은 몇 가지 증거를 제시하십시오. valgrind가 줄 번호를 표시 할 수 있도록 디버그 정보로 컴파일하십시오. –

+0

@ n.m. 당신은 실제로 내가 고려하지 않은 매우 좋은 점을 제기합니다. 나는 단순히이 정확한 문제를 이미 처리 한 프로그램을 보았 기 때문에 double *을 사용했으며 double *을 사용했습니다.float *로 전환하면 오류가 중지되지만 데이터 무결성이 유지되는지 계속 확인합니다. 제가 참조하고있는 원본 라이브러리가 32 비트 용으로 작성되었으며 64 비트 용으로 빌드하고 있다는 사실에 오류가 있는지 궁금합니다. 어둠 속에서 쐈지 만, 32-64에서 마이그레이션 할 때 고려해야 할 사항에 대한 적절한 참고 자료를 알고 계신가요? – user2835725

+0

32-64는 정수 및 포인터 만 부동 소수점 형식의 크기에 영향을주지 않습니다. 어떤 언급도 모르겠다. 미안. –

답변

1

roi->data 경우 유형 T의 숫자의 배열에 대한 포인터입니다, 당신은 작성해야합니다 :

roiData[i] = (int)round(((T*)roi->data)[i]); 

당신은 너무 T 아마 float을해야 float32 값을 사용 주장한다.

+0

감사합니다. 하지만 내가 왜 그 라인을 작품에서 가져 왔는지 (내가이 라이브러리를 재 작성하고 원본을 두 번 작업 한 것) 소스 코드를 설명 할 수 있습니까? 내가 말할 수있는 유일한 점은 빌드 (64 비트, 원래 빌드는 32 비트)입니다. – user2835725