重铸数组,最后一个值总是触发无效的读取异常

时间:2016-11-15 11:52:02

标签: c arrays valgrind

我有一个函数将一堆float32值重新转换为int32,它一直运行到它尝试读取的最后一个float32。即使浮点数不是数组中的最后一个值(即我将FOR循环设置为提前停止),它仍会返回无效的读取,就好像它试图在数组外部读取一样。

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是一个新数组,用于保存从roi->数据中获取的int值(这是一个带有一堆指针值的void *)。在上面,我们从roi-&gt;数据中获取double *,舍入它们的值,并将其作为int存储在roiData中存储。我已多次确认错误与明确读取外部错误无关。数据(它应该有1,048,576个值,它将处理1,048,576个值),但即使我告诉它停止在20,000个值,错误仍然会发生。除了返回0/1语句之外,在for之后没有其他代码。

(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定义为:

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-&gt; data是一个void *,其存储数据类型为nifti_image-&gt; datatype。

在我的代码中,我检查了上面代码所针对的数据类型,它执行上面的操作。

在这种特殊情况下,我知道数据类型应该是float32。

0 个答案:

没有答案