Giter VIP home page Giter VIP logo

Comments (7)

fukuchi avatar fukuchi commented on June 2, 2024 1

Hi @c-273 ,

Thank you for the detailed report. It's very interesting for me. Why it happened only on 64-bit? Anyway, I'm happy to hear that it did not occur in 3.9.0. I'm going to deprecate the 3.4.4 and release 4.0.0 as the next major release. If 3.9.0 is sufficient for your purpose, I'd like to ask you to use 3.9.0. Your further bug report is highly welcome.

from libqrencode.

fukuchi avatar fukuchi commented on June 2, 2024

No, it's not memory leak. When the program exits, the allocated buffer is released by the operating system. If we release it manually, we have to call free() at the very end of the main() of qrenc.c, and it is redundant.

from libqrencode.

c-273 avatar c-273 commented on June 2, 2024

I disagree - if you allocate memory then you should free it when no longer required. You should not depend on any operating system to do it for you!

There also appears to be a memory leak at the end of QRcode_encodeStringReal in grencode.c.
A solution is to call "QRcode_clearCache();" after every call to "QRinput_free(input);". In fact, probably need to call "QRcode_clearCache();" after every call to "QRinput_free(input);" throughout grencode.c.

from libqrencode.

fukuchi avatar fukuchi commented on June 2, 2024

@c-273 ,

To free the memory area pointed by "intext" in qrenc.c, we have to introduce a new variable to handle it for some reason ("intext" may point to an area allocated by the OS, not the application). Plus, the appropriate place to call free(intext) is at the very end of the main(), just before "return 0". It's too much redundant. See https://stackoverflow.com/a/2213836

BTW, the cache mechanism had been eliminated from the latest libqrencode.

Moreover, QRcode_clearCache() is not relevant to QRinput, as far as I understand. Please report the details if you still have a clear evidence of memory leaks.

from libqrencode.

c-273 avatar c-273 commented on June 2, 2024

Thank you.

I do have a memory leak (again 64-bit only, which I don't understand). However, it may well be that this call is required to be added by the user rather than the library but I couldn't find any documentation giving best practices e.g. stating something like: Initialise, Do something, Tidy up. It probably isn't in the library itself and so shouldn't be in this issue.

This is in the Windows version of wxWidgets - creating a wxBitmap from a Unicode string to display as a QR code. The wxWidgets version is only used by Linux users but I test it under Windows. It may well then be implemented in the MFC version of our Open Source application.

We convert the Unicode string to UTF8 format and generate a wxBitmap, which is then shown in a dialog. I have had to add 2 "QRcode_clearCache();" statements (marked ADDED below) to stop the memory leak (I think it is only the last one that is important).

wxBitmap QRCodeBitmap( const std::string &data )
{
	using QRcodePtr = std::unique_ptr<QRcode, decltype(&QRcode_free)>;
	using std::vector;

	CUTF8Conv conv;
	const unsigned char *utf8str = nullptr;
	size_t utf8len = 0;
	if ( !conv.ToUTF8(data, utf8str, utf8len) )
		return wxBitmap();

	auto qc_data = reinterpret_cast<const char *>(utf8str);
	QRcodePtr qc(QRcode_encodeString8bit(qc_data, 0, QR_ECLEVEL_L), &QRcode_free);
	if (!qc || !qc->width) {
		QRcode_clearCache();  // ADDED
		return wxBitmap();
	}

	constexpr unsigned margin = 24;
	constexpr unsigned scale = 8;

	// This is only for the ease of computation, to avoid filling and
	// tracking bytes partially while generating the xbm data
	static_assert( scale % 8 == 0, "QRcode must scale up by a factor of 8");
	static_assert( margin % scale == 0, "margin must be a multiple of scale");

	// in pixels
	const unsigned imageWidth = 2 * margin + scale * qc->width;

	const vector<char> pxTopMargin( (imageWidth*margin) / 8, 0 );
	const vector<char> pxSideMargin( margin / 8, 0);

	// This converts a line of QR data to a line of scaled-up pixels
	// The last bit of QR byte, if 0 => white, else black
	auto qr2xbmp = [&qc, scale](int line) {
		vector<char> pixels(qc->width*scale / 8);
		auto fill_index = pixels.begin();
		auto from = qc->data + line*qc->width;
		auto to = from + qc->width;
		std::for_each(from, to, [&](char byte) {
				const auto bytesToFill = scale / 8;
				// All bits in these bytes are for the same pixel, so
				// its either all 1s, or all 0s
				std::fill_n(fill_index, bytesToFill, byte & 1? 0xff: 0);
				std::advance(fill_index, bytesToFill);
		});
		return pixels;
	};

	vector<char> xbmp(pxTopMargin);
	xbmp.reserve( imageWidth*imageWidth/8 );

	// For each line of QR data, generate a line of pixels
	for (auto line = 0; line < qc->width; ++line) {
		vector<char> pxline(pxSideMargin);
		pxline.reserve( imageWidth / 8 );
		const auto qrdata = qr2xbmp(line);
		wxASSERT( qrdata.size() == (imageWidth - 2 * margin) / 8 );
		pxline.insert(pxline.end(), qrdata.begin(), qrdata.end());
		pxline.insert(pxline.end(), pxSideMargin.begin(), pxSideMargin.end());
		wxASSERT( pxline.size() == imageWidth / 8 );
		// And repeat that line "scale" times
		for (unsigned n = 0; n < scale; ++n)
			xbmp.insert(xbmp.end(), pxline.begin(), pxline.end());
	}
	xbmp.insert(xbmp.end(), pxTopMargin.begin(), pxTopMargin.end());

	QRcode_clearCache();  // ADDED

	return wxBitmap(xbmp.data(), imageWidth, imageWidth);
}
...

from libqrencode.

c-273 avatar c-273 commented on June 2, 2024

Slight update.

  1. Memory leak happens in both 32-bit & 64-bit builds.
  2. The leak is at the end of the routine after inserting data into xbmp. I believe that the first QRcode_clearCache(); is probably unnecessary as the creation of the QR code had failed (but I haven't had an occurrence when this has happened to test this).
  3. If I use QRcode instead of QRcodePtr and then explicitly call QRcode_free(); before returning the wxBitmap rather than let it be called during the destruction of the QRcodePtr when the routine ends, I still get the memory leak.

Thanks for your help with this.

PS. This is with V3.4.4 source of libqrencode compiled with both VS2015 & VS2017. You mentioned that "the cache mechanism had been eliminated from the latest libqrencode". Which version is this and when will it be formally released?

from libqrencode.

c-273 avatar c-273 commented on June 2, 2024

I can confirm that this memory leak has been fixed in version 3.9.0

from libqrencode.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.