| File: | src/unrrdu/jhisto.c |
| Location: | line 156, column 7 |
| Description: | Potential leak of memory pointed to by 'npass' |
| 1 | /* | |||
| 2 | Teem: Tools to process and visualize scientific data and images . | |||
| 3 | Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago | |||
| 4 | Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann | |||
| 5 | Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah | |||
| 6 | ||||
| 7 | This library is free software; you can redistribute it and/or | |||
| 8 | modify it under the terms of the GNU Lesser General Public License | |||
| 9 | (LGPL) as published by the Free Software Foundation; either | |||
| 10 | version 2.1 of the License, or (at your option) any later version. | |||
| 11 | The terms of redistributing and/or modifying this software also | |||
| 12 | include exceptions to the LGPL that facilitate static linking. | |||
| 13 | ||||
| 14 | This library is distributed in the hope that it will be useful, | |||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| 17 | Lesser General Public License for more details. | |||
| 18 | ||||
| 19 | You should have received a copy of the GNU Lesser General Public License | |||
| 20 | along with this library; if not, write to Free Software Foundation, Inc., | |||
| 21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 22 | */ | |||
| 23 | ||||
| 24 | #include "unrrdu.h" | |||
| 25 | #include "privateUnrrdu.h" | |||
| 26 | ||||
| 27 | #define INFO"Create joint histogram of two or more nrrds" "Create joint histogram of two or more nrrds" | |||
| 28 | static const char *_unrrdu_jhistoInfoL = | |||
| 29 | (INFO"Create joint histogram of two or more nrrds" | |||
| 30 | ". Each axis of the output corresponds to one of the " | |||
| 31 | "input nrrds, and each bin in the output records the " | |||
| 32 | "number of corresponding positions in the inputs with " | |||
| 33 | "a combination of values represented by the coordinates " | |||
| 34 | "of the bin.\n " | |||
| 35 | "* Uses nrrdHistoJoint"); | |||
| 36 | ||||
| 37 | int | |||
| 38 | unrrdu_jhistoMain(int argc, const char **argv, const char *me, | |||
| 39 | hestParm *hparm) { | |||
| 40 | hestOpt *opt = NULL((void*)0); | |||
| 41 | char *out, *err; | |||
| 42 | Nrrd **nin, **npass; | |||
| 43 | Nrrd *nout, *nwght; | |||
| 44 | size_t *bin; | |||
| 45 | int type, clamp[NRRD_DIM_MAX16], pret; | |||
| 46 | unsigned int minLen, maxLen, ninLen, binLen, ai, diceax; | |||
| 47 | airArray *mop; | |||
| 48 | double *min, *max; | |||
| 49 | NrrdRange **range; | |||
| 50 | ||||
| 51 | hestOptAdd(&opt, "b,bin", "bins0 bins1", airTypeSize_t, 2, -1, &bin, NULL((void*)0), | |||
| 52 | "bins<i> is the number of bins to use along axis i (of joint " | |||
| 53 | "histogram), which represents the values of nin<i> ", | |||
| 54 | &binLen); | |||
| 55 | hestOptAdd(&opt, "w,weight", "nweight", airTypeOther, 1, 1, &nwght, "", | |||
| 56 | "how to weigh contributions to joint histogram. By default " | |||
| 57 | "(not using this option), the increment is one bin count per " | |||
| 58 | "sample, but by giving a nrrd, the value in the nrrd at the " | |||
| 59 | "corresponding location will be the bin count increment ", | |||
| 60 | NULL((void*)0), NULL((void*)0), nrrdHestNrrd); | |||
| 61 | hestOptAdd(&opt, "min,minimum", "min0 min1", airTypeDouble, 2, -1, | |||
| 62 | &min, "nan nan", | |||
| 63 | "min<i> is the low range of values to be quantized along " | |||
| 64 | "axis i; use \"nan\" to represent lowest value present ", | |||
| 65 | &minLen); | |||
| 66 | hestOptAdd(&opt, "max,maximum", "max0 max1", airTypeDouble, 2, -1, | |||
| 67 | &max, "nan nan", | |||
| 68 | "max<i> is the high range of values to be quantized along " | |||
| 69 | "axis i; use \"nan\" to represent highest value present ", | |||
| 70 | &maxLen); | |||
| 71 | OPT_ADD_TYPE(type, "type to use for output (the type used to store hit "hestOptAdd(&opt, "t,type", "type", airTypeEnum, 1, 1, & (type), "uint", "type to use for output (the type used to store hit " "counts in the joint histogram). Clamping is done on hit " "counts so that they never overflow a fixed-point type" , ((void*)0), nrrdType) | |||
| 72 | "counts in the joint histogram). Clamping is done on hit "hestOptAdd(&opt, "t,type", "type", airTypeEnum, 1, 1, & (type), "uint", "type to use for output (the type used to store hit " "counts in the joint histogram). Clamping is done on hit " "counts so that they never overflow a fixed-point type" , ((void*)0), nrrdType) | |||
| 73 | "counts so that they never overflow a fixed-point type",hestOptAdd(&opt, "t,type", "type", airTypeEnum, 1, 1, & (type), "uint", "type to use for output (the type used to store hit " "counts in the joint histogram). Clamping is done on hit " "counts so that they never overflow a fixed-point type" , ((void*)0), nrrdType) | |||
| 74 | "uint")hestOptAdd(&opt, "t,type", "type", airTypeEnum, 1, 1, & (type), "uint", "type to use for output (the type used to store hit " "counts in the joint histogram). Clamping is done on hit " "counts so that they never overflow a fixed-point type" , ((void*)0), nrrdType); | |||
| 75 | hestOptAdd(&opt, "i,input", "nin0 [nin1]", airTypeOther, 1, -1, &nin, "-", | |||
| 76 | "list of nrrds (one for each axis of joint histogram), " | |||
| 77 | "or, single nrrd that will be sliced along specified axis.", | |||
| 78 | &ninLen, NULL((void*)0), nrrdHestNrrd); | |||
| 79 | hestOptAdd(&opt, "a,axis", "axis", airTypeUInt, 1, 1, &diceax, "0", | |||
| 80 | "axis to slice along when working with single nrrd. "); | |||
| 81 | OPT_ADD_NOUT(out, "output nrrd")hestOptAdd(&opt, "o,output", "nout", airTypeString, 1, 1, &(out), "-", "output nrrd"); | |||
| 82 | ||||
| 83 | mop = airMopNew(); | |||
| 84 | airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); | |||
| 85 | ||||
| 86 | USAGE(_unrrdu_jhistoInfoL)if (!argc) { hestInfo(__stdoutp, me, (_unrrdu_jhistoInfoL), hparm ); hestUsage(__stdoutp, opt, me, hparm); hestGlossary(__stdoutp , opt, hparm); airMopError(mop); return 0; }; | |||
| 87 | PARSE()if ((pret=hestParse(opt, argc, argv, &err, hparm))) { if ( 1 == pret || 2 == pret) { if (!(getenv("UNRRDU_QUIET_QUIT") && airEndsWith(err, "[nrrd] _nrrdRead: immediately hit EOF" "\n" ))) { fprintf(__stderrp, "%s: %s\n", me, err); free(err); hestUsage (__stderrp, opt, me, hparm); hestGlossary(__stderrp, opt, hparm ); } airMopError(mop); return 1; } else { exit(1); } }; | |||
| 88 | airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); | |||
| 89 | ||||
| 90 | if (ninLen == 1) { | |||
| ||||
| 91 | /* Slice a nrrd on the fly */ | |||
| 92 | size_t asize; | |||
| 93 | if (!( diceax <= nin[0]->dim-1 )) { | |||
| 94 | fprintf(stderr__stderrp, "%s: slice axis %u not valid for single %u-D nrrd", | |||
| 95 | me, diceax, nin[0]->dim); | |||
| 96 | airMopError(mop); | |||
| 97 | return 1; | |||
| 98 | } | |||
| 99 | asize = nin[0]->axis[diceax].size; | |||
| 100 | if (asize != binLen) { | |||
| 101 | fprintf(stderr__stderrp, | |||
| 102 | "%s: size (%u) of slice axis %u != # bins given (%u)\n", me, | |||
| 103 | AIR_CAST(unsigned int, asize)((unsigned int)(asize)), diceax, | |||
| 104 | AIR_CAST(unsigned int, binLen)((unsigned int)(binLen))); | |||
| 105 | airMopError(mop); | |||
| 106 | return 1; | |||
| 107 | } | |||
| 108 | /* create buffer for slices */ | |||
| 109 | if (!( npass = AIR_CALLOC(binLen, Nrrd*)(Nrrd**)(calloc((binLen), sizeof(Nrrd*))) )) { | |||
| 110 | fprintf(stderr__stderrp, "%s: couldn't allocate nrrd array (size %u)\n", | |||
| 111 | me, binLen); | |||
| 112 | airMopError(mop); return 1; | |||
| 113 | } | |||
| 114 | airMopMem(mop, &npass, airMopAlways); | |||
| 115 | /* slice this nrrd, allocate new nrrds, and store the slices in nin */ | |||
| 116 | for (ai=0; ai<binLen; ai++) { | |||
| 117 | /* Allocate each slice nrrd */ | |||
| 118 | if (!( npass[ai] = nrrdNew() )) { | |||
| 119 | fprintf(stderr__stderrp, "%s: couldn't allocate npass[%u]\n", me, ai); | |||
| 120 | airMopError(mop); return 1; | |||
| 121 | } | |||
| 122 | airMopAdd(mop, npass[ai], (airMopper)nrrdNuke, airMopAlways); | |||
| 123 | if (nrrdSlice(npass[ai], nin[0], diceax, ai)) { | |||
| 124 | airMopAdd(mop, err = biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways); | |||
| 125 | fprintf(stderr__stderrp, "%s: error slicing:\n%s", me, err); | |||
| 126 | airMopError(mop); return 1; | |||
| 127 | } | |||
| 128 | } | |||
| 129 | } else { | |||
| 130 | /* we were given multiple nrrds */ | |||
| 131 | if (ninLen != binLen) { | |||
| 132 | fprintf(stderr__stderrp, | |||
| 133 | "%s: # input nrrds (%u) != # bin specifications (%u)\n", me, | |||
| 134 | AIR_CAST(unsigned int, ninLen)((unsigned int)(ninLen)), AIR_CAST(unsigned int, binLen)((unsigned int)(binLen))); | |||
| 135 | airMopError(mop); | |||
| 136 | return 1; | |||
| 137 | } | |||
| 138 | /* create buffer for slices (HEY copy and paste) */ | |||
| 139 | if (!( npass = AIR_CALLOC(binLen, Nrrd*)(Nrrd**)(calloc((binLen), sizeof(Nrrd*))) )) { | |||
| 140 | fprintf(stderr__stderrp, "%s: couldn't allocate nrrd array (size %u)\n", | |||
| 141 | me, binLen); | |||
| 142 | airMopError(mop); return 1; | |||
| 143 | } | |||
| 144 | for (ai=0; ai<binLen; ai++) { | |||
| 145 | npass[ai] = nin[ai]; | |||
| 146 | } | |||
| 147 | } | |||
| 148 | range = AIR_CALLOC(binLen, NrrdRange*)(NrrdRange**)(calloc((binLen), sizeof(NrrdRange*))); | |||
| 149 | airMopAdd(mop, range, airFree, airMopAlways); | |||
| 150 | for (ai=0; ai<binLen; ai++) { | |||
| 151 | range[ai] = nrrdRangeNew(AIR_NAN(airFloatQNaN.f), AIR_NAN(airFloatQNaN.f)); | |||
| 152 | airMopAdd(mop, range[ai], (airMopper)nrrdRangeNix, airMopAlways); | |||
| 153 | } | |||
| 154 | if (2 != minLen || (AIR_EXISTS(min[0])(((int)(!((min[0]) - (min[0]))))) || AIR_EXISTS(min[1])(((int)(!((min[1]) - (min[1]))))))) { | |||
| 155 | if (minLen != binLen) { | |||
| 156 | fprintf(stderr__stderrp, "%s: # mins (%d) != # input nrrds (%d)\n", me, | |||
| ||||
| 157 | minLen, binLen); | |||
| 158 | airMopError(mop); return 1; | |||
| 159 | } | |||
| 160 | for (ai=0; ai<binLen; ai++) { | |||
| 161 | range[ai]->min = min[ai]; | |||
| 162 | } | |||
| 163 | } | |||
| 164 | if (2 != maxLen || (AIR_EXISTS(max[0])(((int)(!((max[0]) - (max[0]))))) || AIR_EXISTS(max[1])(((int)(!((max[1]) - (max[1]))))))) { | |||
| 165 | if (maxLen != binLen) { | |||
| 166 | fprintf(stderr__stderrp, "%s: # maxs (%d) != # input nrrds (%d)\n", me, | |||
| 167 | maxLen, binLen); | |||
| 168 | airMopError(mop); return 1; | |||
| 169 | } | |||
| 170 | for (ai=0; ai<binLen; ai++) { | |||
| 171 | range[ai]->max = max[ai]; | |||
| 172 | } | |||
| 173 | } | |||
| 174 | for (ai=0; ai<binLen; ai++) { | |||
| 175 | clamp[ai] = 0; | |||
| 176 | } | |||
| 177 | ||||
| 178 | nout = nrrdNew(); | |||
| 179 | airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); | |||
| 180 | ||||
| 181 | if (nrrdHistoJoint(nout, (const Nrrd*const*)npass, | |||
| 182 | (const NrrdRange*const*)range, | |||
| 183 | binLen, nwght, bin, type, clamp)) { | |||
| 184 | airMopAdd(mop, err = biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways); | |||
| 185 | fprintf(stderr__stderrp, "%s: error doing joint histogram:\n%s", me, err); | |||
| 186 | airMopError(mop); | |||
| 187 | return 1; | |||
| 188 | } | |||
| 189 | ||||
| 190 | SAVE(out, nout, NULL)if (nrrdSave((out), (nout), (((void*)0)))) { airMopAdd(mop, err = biffGetDone(nrrdBiffKey), airFree, airMopAlways); fprintf( __stderrp, "%s: error saving nrrd to \"%s\":\n%s\n", me, (out ), err); airMopError(mop); return 1; }; | |||
| 191 | ||||
| 192 | airMopOkay(mop); | |||
| 193 | return 0; | |||
| 194 | } | |||
| 195 | ||||
| 196 | UNRRDU_CMD(jhisto, INFO)unrrduCmd unrrdu_jhistoCmd = { "jhisto", "Create joint histogram of two or more nrrds" , unrrdu_jhistoMain, 0 }; |