2016-11-15 2 views
0

У меня есть функция, которая переводит кучу значений float32 в int32 и работает до самого последнего float32, который он пытается прочитать. даже если этот float не является последним значением в массиве (т. е. я устанавливаю цикл FOR для остановки раньше), он все равно возвращает недопустимое чтение, как если бы он пытался читать вне массива.reasting array, последнее значение всегда вызывает недопустимое исключение чтения.

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 определен вне функции переделки как:

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

roiData новый массив, который предназначен для хранения значений INT, которые взяты из roi-> данных (что является недействительным * с кучей значений указателя в нем). в приведенном выше примере мы берем double * из roi-> данных, округляя их значение и бросая это как int для хранения в roiData. Я неоднократно подтверждал, что ошибка не связана с явным чтением внешних данных roi> (она должна содержать 1 048 576 значений внутри нее, и она будет обрабатывать 1 045 576 значений), но ошибка все еще происходит, даже если я скажу ей остановиться на 20 000 значений. после кода for нет другого кода, кроме выражения return 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»).

редактировать: дополнительная информация:

рои определяется как:

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-> данных является недействительным * которого хранится тип данных nifti_image-> тип данных.

Ранее в моем коде я проверяю тип данных, в котором также указан вышеприведенный код, который выполняет вышеуказанные операции над ним.

В этом конкретном случае я знаю, что тип данных СЛЕДУЕТ быть float32.

+1

Я не вижу никакого float32, определенного где угодно. Существует двойной, который редко является 32-битным типом. 1 миллион удваивается, как правило, занимает 8 миллионов байт, а valgrind говорит, что выделено только 4 миллиона байт. Вы пытаетесь прочитать миллион значений. Я не вижу никаких доказательств нарушения, произошедшего после того, как было меньше, чем полное количество просмотров. Пожалуйста, покажите некоторые доказательства, то есть код и связанный журнал valgrind. Скомпилируйте с информацией об отладке, чтобы valgrind мог отображать номера строк. –

+0

@ н.м. Вы действительно поднимаете очень хороший момент, который я не рассматривал. Я использовал double *, потому что я просто посмотрел, как программа, которую я переписываю, уже обрабатывала эту точную проблему, и они использовали double *.переключение на float * заставляет ошибку остановиться, но я все еще проверяю, что целостность данных поддерживается. Мне интересно, если это ошибка из-за того, что исходная библиотека, на которую я ссылаюсь, была построена для 32-битной, и я строю для 64-битной. выстрелил в темноте, но любой шанс, что вы знаете приличную ссылку на изменения соображений перехода от 32-64? – user2835725

+0

32-64 не влияет на размеры типов с плавающей точкой, только целые числа и указатели. Не знаю никаких ссылок, извините. –

ответ

1

Если roi->data является указателем на массив чисел типа T, то вы должны написать:

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

Вы утверждаете использовать float32 значения так T, вероятно, следует float.

+0

спасибо. но можете ли вы объяснить, почему исходный код я взял эту строку из работы (я делаю переписывание этой библиотеки и в оригинальной двойной * работает). Единственное, что я могу сказать, это другое - это сборка (я на 64-битной, оригинальная сборка была 32 бит). – user2835725

Смежные вопросы