C++ port: some memory leak cleanups

Closes Issue 499 and Issue 496.

git-svn-id: https://zxing.googlecode.com/svn/trunk@1510 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
flyashi 2010-08-06 18:59:07 +00:00
parent 2de913d220
commit 5a4f5c901d
8 changed files with 903 additions and 895 deletions

View file

@ -62,25 +62,25 @@ namespace zxing {
hints.containsFormat(BarcodeFormat_CODE_39) || hints.containsFormat(BarcodeFormat_CODE_39) ||
hints.containsFormat(BarcodeFormat_ITF); hints.containsFormat(BarcodeFormat_ITF);
if (addOneDReader && !tryHarder) { if (addOneDReader && !tryHarder) {
readers_.push_back(new zxing::oned::MultiFormatOneDReader(hints)); readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
} }
if (hints.containsFormat(BarcodeFormat_QR_CODE)) { if (hints.containsFormat(BarcodeFormat_QR_CODE)) {
readers_.push_back(new zxing::qrcode::QRCodeReader()); readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader()));
} }
if (hints.containsFormat(BarcodeFormat_DATA_MATRIX)) { if (hints.containsFormat(BarcodeFormat_DATA_MATRIX)) {
readers_.push_back(new zxing::datamatrix::DataMatrixReader()); readers_.push_back(Ref<Reader>(new zxing::datamatrix::DataMatrixReader()));
} }
//TODO: add PDF417 here once PDF417 reader is implemented //TODO: add PDF417 here once PDF417 reader is implemented
if (addOneDReader && tryHarder) { if (addOneDReader && tryHarder) {
readers_.push_back(new zxing::oned::MultiFormatOneDReader(hints)); readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
} }
if (readers_.size() == 0) { if (readers_.size() == 0) {
if (!tryHarder) { if (!tryHarder) {
readers_.push_back(new zxing::oned::MultiFormatOneDReader(hints)); readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
} }
readers_.push_back(new zxing::qrcode::QRCodeReader()); readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader()));
if (tryHarder) { if (tryHarder) {
readers_.push_back(new zxing::oned::MultiFormatOneDReader(hints)); readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
} }
} }
} }
@ -97,8 +97,6 @@ namespace zxing {
} }
MultiFormatReader::~MultiFormatReader() { MultiFormatReader::~MultiFormatReader() {
for (unsigned int i = 0; i < readers_.size(); i++) {
delete readers_[i];
}
} }
} }

View file

@ -32,7 +32,7 @@ namespace zxing {
private: private:
Ref<Result> decodeInternal(Ref<BinaryBitmap> image); Ref<Result> decodeInternal(Ref<BinaryBitmap> image);
std::vector<Reader*> readers_; std::vector<Ref<Reader> > readers_;
DecodeHints hints_; DecodeHints hints_;
public: public:

View file

@ -55,7 +55,9 @@ Ref<BitArray> GlobalHistogramBinarizer::getBlackRow(int y, Ref<BitArray> row) {
} }
//TODO(flyashi): cache this instead of allocating and deleting per row //TODO(flyashi): cache this instead of allocating and deleting per row
unsigned char* row_pixels = new unsigned char[width]; unsigned char* row_pixels = NULL;
try {
row_pixels = new unsigned char[width];
getLuminanceSource()->getRow(y,row_pixels); getLuminanceSource()->getRow(y,row_pixels);
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
histogram[row_pixels[x] >> LUMINANCE_SHIFT]++; histogram[row_pixels[x] >> LUMINANCE_SHIFT]++;
@ -84,6 +86,10 @@ Ref<BitArray> GlobalHistogramBinarizer::getBlackRow(int y, Ref<BitArray> row) {
delete [] row_pixels; delete [] row_pixels;
return array_ref; return array_ref;
} catch (IllegalArgumentException const& iae) {
delete [] row_pixels;
throw iae;
}
} }
Ref<BitMatrix> GlobalHistogramBinarizer::getBlackMatrix() { Ref<BitMatrix> GlobalHistogramBinarizer::getBlackMatrix() {

View file

@ -75,9 +75,16 @@ namespace oned {
} }
Code39Reader::Code39Reader(bool usingCheckDigit_, bool extendedMode_) :
alphabet_string(ALPHABET_STRING),
usingCheckDigit(usingCheckDigit_),
extendedMode(extendedMode_) {
}
Ref<Result> Code39Reader::decodeRow(int rowNumber, Ref<BitArray> row){ Ref<Result> Code39Reader::decodeRow(int rowNumber, Ref<BitArray> row){
int* start = findAsteriskPattern(row); int* start = NULL;
try {
start = findAsteriskPattern(row);
int nextStart = start[1]; int nextStart = start[1];
int end = row->getSize(); int end = row->getSize();
@ -88,23 +95,17 @@ namespace oned {
std::string tmpResultString; std::string tmpResultString;
int countersLen = 9; const int countersLen = 9;
int* counters = new int[countersLen]; int counters[countersLen];
for (int i = 0; i < countersLen; i++) { for (int i = 0; i < countersLen; i++) {
counters[i] = 0; counters[i] = 0;
} }
char decodedChar; char decodedChar;
int lastStart; int lastStart;
do { do {
try {
recordPattern(row, nextStart, counters, countersLen); recordPattern(row, nextStart, counters, countersLen);
} catch (ReaderException re) {
delete [] start;
throw re;
}
int pattern = toNarrowWidePattern(counters, countersLen); int pattern = toNarrowWidePattern(counters, countersLen);
if (pattern < 0) { if (pattern < 0) {
delete [] start;
throw ReaderException("pattern < 0"); throw ReaderException("pattern < 0");
} }
decodedChar = patternToChar(pattern); decodedChar = patternToChar(pattern);
@ -125,14 +126,10 @@ namespace oned {
for (int i = 0; i < countersLen; i++) { for (int i = 0; i < countersLen; i++) {
lastPatternSize += counters[i]; lastPatternSize += counters[i];
} }
// IS begin
delete [] counters;
// IS end
int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize; int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;
// If 50% of last pattern size, following last pattern, is not whitespace, // If 50% of last pattern size, following last pattern, is not whitespace,
// fail (but if it's whitespace to the very end of the image, that's OK) // fail (but if it's whitespace to the very end of the image, that's OK)
if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) { if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) {
delete [] start;
throw ReaderException("too short end white space"); throw ReaderException("too short end white space");
} }
@ -148,17 +145,12 @@ namespace oned {
tmpResultString.erase(max, 1); tmpResultString.erase(max, 1);
} }
Ref<String> resultString(new String(tmpResultString)); Ref<String> resultString(new String(tmpResultString));
if (extendedMode) { if (extendedMode) {
delete resultString;
resultString = decodeExtended(tmpResultString); resultString = decodeExtended(tmpResultString);
} }
if (tmpResultString.length() == 0) { if (tmpResultString.length() == 0) {
delete [] start;
// Almost surely a false positive // Almost surely a false positive
throw ReaderException(""); throw ReaderException("");
} }
@ -176,11 +168,15 @@ namespace oned {
ArrayRef<unsigned char> resultBytes(1); ArrayRef<unsigned char> resultBytes(1);
delete [] start;
Ref<Result> res(new Result( Ref<Result> res(new Result(
resultString, resultBytes, resultPoints, BarcodeFormat_CODE_39)); resultString, resultBytes, resultPoints, BarcodeFormat_CODE_39));
delete [] start;
return res; return res;
} catch (ReaderException const& re) {
delete [] start;
throw re;
}
} }
int* Code39Reader::findAsteriskPattern(Ref<BitArray> row){ int* Code39Reader::findAsteriskPattern(Ref<BitArray> row){
@ -194,8 +190,8 @@ namespace oned {
} }
int counterPosition = 0; int counterPosition = 0;
int countersLen = 9; const int countersLen = 9;
int* counters = new int[countersLen]; int counters[countersLen];
for (int i = 0; i < countersLen; i++) { for (int i = 0; i < countersLen; i++) {
counters[i] = 0; counters[i] = 0;
} }
@ -235,9 +231,6 @@ namespace oned {
isWhite = !isWhite; isWhite = !isWhite;
} }
} }
// IS begin
delete [] counters;
// IS end
throw ReaderException(""); throw ReaderException("");
} }

View file

@ -52,7 +52,9 @@ namespace zxing {
determineFirstDigit(resultString, lgPatternFound); determineFirstDigit(resultString, lgPatternFound);
int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN()); int* middleRange = 0;
try {
middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN());
rowOffset = middleRange[1]; rowOffset = middleRange[1];
for (int x = 0; x < 6 && rowOffset < end; x++) { for (int x = 0; x < 6 && rowOffset < end; x++) {
@ -63,7 +65,12 @@ namespace zxing {
} }
} }
delete [] middleRange;
return rowOffset; return rowOffset;
} catch (ReaderException const& re) {
delete [] middleRange;
throw re;
}
} }
void EAN13Reader::determineFirstDigit(std::string& resultString, int lgPatternFound){ void EAN13Reader::determineFirstDigit(std::string& resultString, int lgPatternFound){

View file

@ -41,7 +41,9 @@ namespace zxing {
} }
} }
int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN()); int* middleRange = 0;
try {
middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN());
rowOffset = middleRange[1]; rowOffset = middleRange[1];
for (int x = 0; x < 4 && rowOffset < end; x++) { for (int x = 0; x < 4 && rowOffset < end; x++) {
@ -52,7 +54,12 @@ namespace zxing {
} }
} }
delete [] middleRange;
return rowOffset; return rowOffset;
} catch (ReaderException const& re) {
delete [] middleRange;
throw re;
}
} }
BarcodeFormat EAN8Reader::getBarcodeFormat(){ BarcodeFormat EAN8Reader::getBarcodeFormat(){

View file

@ -67,24 +67,15 @@ namespace zxing {
Ref<Result> ITFReader::decodeRow(int rowNumber, Ref<BitArray> row){ Ref<Result> ITFReader::decodeRow(int rowNumber, Ref<BitArray> row){
// Find out where the Middle section (payload) starts & ends int* startRange = 0;
int* startRange = decodeStart(row); int* endRange = 0;
int* endRange;
try { try {
// Find out where the Middle section (payload) starts & ends
startRange = decodeStart(row);
endRange = decodeEnd(row); endRange = decodeEnd(row);
} catch (ReaderException re) {
delete [] startRange;
throw re;
}
std::string tmpResult; std::string tmpResult;
try {
decodeMiddle(row, startRange[1], endRange[0], tmpResult); decodeMiddle(row, startRange[1], endRange[0], tmpResult);
} catch (zxing::ReaderException re) {
delete [] startRange;
delete [] endRange;
throw re;
}
// To avoid false positives with 2D barcodes (and other patterns), make // To avoid false positives with 2D barcodes (and other patterns), make
// an assumption that the decoded string must be 6, 10 or 14 digits. // an assumption that the decoded string must be 6, 10 or 14 digits.
@ -94,8 +85,6 @@ namespace zxing {
lengthOK = true; lengthOK = true;
} }
if (!lengthOK) { if (!lengthOK) {
delete [] startRange;
delete [] endRange;
throw ReaderException("not enough characters count"); throw ReaderException("not enough characters count");
} }
@ -109,11 +98,15 @@ namespace zxing {
ArrayRef<unsigned char> resultBytes(1); ArrayRef<unsigned char> resultBytes(1);
Ref<Result> res(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_ITF));
delete [] startRange; delete [] startRange;
delete [] endRange; delete [] endRange;
Ref<Result> res(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_ITF));
return res; return res;
} catch (ReaderException re) {
delete [] startRange;
delete [] endRange;
throw re;
}
} }
/** /**
@ -173,7 +166,9 @@ namespace zxing {
int* ITFReader::decodeStart(Ref<BitArray> row){ int* ITFReader::decodeStart(Ref<BitArray> row){
int endStart = skipWhiteSpace(row); int endStart = skipWhiteSpace(row);
/// static int* findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen); /// static int* findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen);
int* startPattern = findGuardPattern(row, endStart, START_PATTERN, START_PATTERN_LEN); int* startPattern = 0;
try {
startPattern = findGuardPattern(row, endStart, START_PATTERN, START_PATTERN_LEN);
// Determine the width of a narrow line in pixels. We can do this by // Determine the width of a narrow line in pixels. We can do this by
// getting the width of the start pattern and dividing by 4 because its // getting the width of the start pattern and dividing by 4 because its
@ -183,6 +178,10 @@ namespace zxing {
validateQuietZone(row, startPattern[0]); validateQuietZone(row, startPattern[0]);
return startPattern; return startPattern;
} catch (ReaderException re) {
delete [] startPattern;
throw re;
}
} }
/** /**
@ -198,9 +197,10 @@ namespace zxing {
// For convenience, reverse the row and then // For convenience, reverse the row and then
// search from 'the start' for the end block // search from 'the start' for the end block
row->reverse(); row->reverse();
int* endPattern = 0;
try { try {
int endStart = skipWhiteSpace(row); int endStart = skipWhiteSpace(row);
int* endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED, END_PATTERN_REVERSED_LEN); endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED, END_PATTERN_REVERSED_LEN);
// The start & end patterns must be pre/post fixed by a quiet zone. This // The start & end patterns must be pre/post fixed by a quiet zone. This
// zone must be at least 10 times the width of a narrow line. // zone must be at least 10 times the width of a narrow line.
@ -217,6 +217,7 @@ namespace zxing {
row->reverse(); row->reverse();
return endPattern; return endPattern;
} catch (ReaderException re) { } catch (ReaderException re) {
delete [] endPattern;
row->reverse(); row->reverse();
throw re; throw re;
} }

View file

@ -94,24 +94,27 @@ namespace zxing {
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) { Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
return decodeRow(rowNumber, row, findStartGuardPattern(row)); int* start = NULL;
try {
start = findStartGuardPattern(row);
Ref<Result> result = decodeRow(rowNumber, row, start);
delete [] start;
return result;
} catch (ReaderException const& re) {
delete [] start;
throw re;
}
} }
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]){
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]){
int* endRange = NULL;
try {
std::string tmpResultString; std::string tmpResultString;
std::string& tmpResultStringRef = tmpResultString; std::string& tmpResultStringRef = tmpResultString;
int endStart; int endStart;
try {
endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , tmpResultStringRef); endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , tmpResultStringRef);
} catch (ReaderException re) {
if (startGuardRange!=NULL) {
delete [] startGuardRange;
startGuardRange = NULL;
}
throw re;
}
int* endRange = decodeEnd(row, endStart); endRange = decodeEnd(row, endStart);
// Make sure there is a quiet zone at least as big as the end pattern after the barcode. The // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The
// spec might want more whitespace, but in practice this is the maximum we can count on. // spec might want more whitespace, but in practice this is the maximum we can count on.
@ -122,14 +125,6 @@ namespace zxing {
} }
if (!checkChecksum(tmpResultString)) { if (!checkChecksum(tmpResultString)) {
if (startGuardRange!=NULL) {
delete [] startGuardRange;
startGuardRange = NULL;
}
if (endRange!=NULL) {
delete [] endRange;
endRange = NULL;
}
throw ReaderException("Checksum fail."); throw ReaderException("Checksum fail.");
} }
@ -146,17 +141,14 @@ namespace zxing {
ArrayRef<unsigned char> resultBytes(1); ArrayRef<unsigned char> resultBytes(1);
if (startGuardRange!=NULL) { Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
delete [] startGuardRange;
startGuardRange = NULL;
}
if (endRange!=NULL) {
delete [] endRange; delete [] endRange;
endRange = NULL; return res;
} catch (ReaderException const& re) {
delete [] endRange;
throw re;
} }
Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
return res;
} }
int* UPCEANReader::findStartGuardPattern(Ref<BitArray> row){ int* UPCEANReader::findStartGuardPattern(Ref<BitArray> row){
@ -164,7 +156,10 @@ namespace zxing {
int* startRange = NULL; int* startRange = NULL;
int nextStart = 0; int nextStart = 0;
try {
while (!foundStart) { while (!foundStart) {
delete [] startRange;
startRange = NULL;
startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, sizeof(START_END_PATTERN)/sizeof(int)); startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, sizeof(START_END_PATTERN)/sizeof(int));
int start = startRange[0]; int start = startRange[0];
nextStart = startRange[1]; nextStart = startRange[1];
@ -175,16 +170,17 @@ namespace zxing {
if (quietStart >= 0) { if (quietStart >= 0) {
foundStart = row->isRange(quietStart, start, false); foundStart = row->isRange(quietStart, start, false);
} }
if (!foundStart) {
delete [] startRange;
}
} }
return startRange; return startRange;
} catch (ReaderException const& re) {
delete [] startRange;
throw re;
}
} }
// TODO(flyashi): Return a pair<int, int> for return value to avoid using the heap.
int* UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen){ int* UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen){
int patternLength = patternLen; int patternLength = patternLen;
int counters[patternLength]; int counters[patternLength];
int countersCount = sizeof(counters) / sizeof(int); int countersCount = sizeof(counters) / sizeof(int);
for (int i = 0; i < countersCount; i++) { for (int i = 0; i < countersCount; i++) {