zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit a4fbe0dfd59780f77e5902736a616cda27efde17
parent cf8389d298b33d65fa26ed586aed5aac05a0be4e
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Thu, 13 May 2010 12:16:19 -0400

XML: Memory leak

Diffstat:
Msrc/Misc/Bank.cpp | 7+++----
Msrc/Misc/Config.cpp | 57++++++++++++++++++++++++++++-----------------------------
Msrc/Misc/XMLwrapper.cpp | 23++++++++++++++---------
Msrc/Tests/XMLwrapperTest.h | 20++++++++++++++++++++
4 files changed, 65 insertions(+), 42 deletions(-)

diff --git a/src/Misc/Bank.cpp b/src/Misc/Bank.cpp @@ -609,11 +609,10 @@ int Bank::addtobank(int pos, const char *filename, const char *name) //see if PADsynth is used if(config.cfg.CheckPADsynth) { - XMLwrapper *xml = new XMLwrapper(); - xml->loadXMLfile(ins[pos].filename); + XMLwrapper xml; + xml.loadXMLfile(ins[pos].filename); - ins[pos].info.PADsynth_used = xml->hasPadSynth(); - delete xml; + ins[pos].info.PADsynth_used = xml.hasPadSynth(); } else ins[pos].info.PADsynth_used = false; diff --git a/src/Misc/Config.cpp b/src/Misc/Config.cpp @@ -225,110 +225,109 @@ void Config::clearpresetsdirlist() void Config::readConfig(const char *filename) { - XMLwrapper *xmlcfg = new XMLwrapper(); - if(xmlcfg->loadXMLfile(filename) < 0) + XMLwrapper xmlcfg; + if(xmlcfg.loadXMLfile(filename) < 0) return; - if(xmlcfg->enterbranch("CONFIGURATION")) { - cfg.SampleRate = xmlcfg->getpar("sample_rate", + if(xmlcfg.enterbranch("CONFIGURATION")) { + cfg.SampleRate = xmlcfg.getpar("sample_rate", cfg.SampleRate, 4000, 1024000); - cfg.SoundBufferSize = xmlcfg->getpar("sound_buffer_size", + cfg.SoundBufferSize = xmlcfg.getpar("sound_buffer_size", cfg.SoundBufferSize, 16, 8192); - cfg.OscilSize = xmlcfg->getpar("oscil_size", + cfg.OscilSize = xmlcfg.getpar("oscil_size", cfg.OscilSize, MAX_AD_HARMONICS * 2, 131072); - cfg.SwapStereo = xmlcfg->getpar("swap_stereo", + cfg.SwapStereo = xmlcfg.getpar("swap_stereo", cfg.SwapStereo, 0, 1); - cfg.BankUIAutoClose = xmlcfg->getpar("bank_window_auto_close", + cfg.BankUIAutoClose = xmlcfg.getpar("bank_window_auto_close", cfg.BankUIAutoClose, 0, 1); - cfg.DumpNotesToFile = xmlcfg->getpar("dump_notes_to_file", + cfg.DumpNotesToFile = xmlcfg.getpar("dump_notes_to_file", cfg.DumpNotesToFile, 0, 1); - cfg.DumpAppend = xmlcfg->getpar("dump_append", + cfg.DumpAppend = xmlcfg.getpar("dump_append", cfg.DumpAppend, 0, 1); - xmlcfg->getparstr("dump_file", cfg.DumpFile, MAX_STRING_SIZE); + xmlcfg.getparstr("dump_file", cfg.DumpFile, MAX_STRING_SIZE); - cfg.GzipCompression = xmlcfg->getpar("gzip_compression", + cfg.GzipCompression = xmlcfg.getpar("gzip_compression", cfg.GzipCompression, 0, 9); - xmlcfg->getparstr("bank_current", cfg.currentBankDir, MAX_STRING_SIZE); - cfg.Interpolation = xmlcfg->getpar("interpolation", + xmlcfg.getparstr("bank_current", cfg.currentBankDir, MAX_STRING_SIZE); + cfg.Interpolation = xmlcfg.getpar("interpolation", cfg.Interpolation, 0, 1); - cfg.CheckPADsynth = xmlcfg->getpar("check_pad_synth", + cfg.CheckPADsynth = xmlcfg.getpar("check_pad_synth", cfg.CheckPADsynth, 0, 1); - cfg.UserInterfaceMode = xmlcfg->getpar("user_interface_mode", + cfg.UserInterfaceMode = xmlcfg.getpar("user_interface_mode", cfg.UserInterfaceMode, 0, 2); - cfg.VirKeybLayout = xmlcfg->getpar("virtual_keyboard_layout", + cfg.VirKeybLayout = xmlcfg.getpar("virtual_keyboard_layout", cfg.VirKeybLayout, 0, 10); //get bankroot dirs for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) { - if(xmlcfg->enterbranch("BANKROOT", i)) { + if(xmlcfg.enterbranch("BANKROOT", i)) { cfg.bankRootDirList[i] = new char[MAX_STRING_SIZE]; - xmlcfg->getparstr("bank_root", + xmlcfg.getparstr("bank_root", cfg.bankRootDirList[i], MAX_STRING_SIZE); - xmlcfg->exitbranch(); + xmlcfg.exitbranch(); } } //get preset root dirs for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) { - if(xmlcfg->enterbranch("PRESETSROOT", i)) { + if(xmlcfg.enterbranch("PRESETSROOT", i)) { cfg.presetsDirList[i] = new char[MAX_STRING_SIZE]; - xmlcfg->getparstr("presets_root", + xmlcfg.getparstr("presets_root", cfg.presetsDirList[i], MAX_STRING_SIZE); - xmlcfg->exitbranch(); + xmlcfg.exitbranch(); } } //linux stuff - xmlcfg->getparstr("linux_oss_wave_out_dev", + xmlcfg.getparstr("linux_oss_wave_out_dev", cfg.LinuxOSSWaveOutDev, MAX_STRING_SIZE); - xmlcfg->getparstr("linux_oss_seq_in_dev", + xmlcfg.getparstr("linux_oss_seq_in_dev", cfg.LinuxOSSSeqInDev, MAX_STRING_SIZE); //windows stuff - cfg.WindowsWaveOutId = xmlcfg->getpar("windows_wave_out_id", + cfg.WindowsWaveOutId = xmlcfg.getpar("windows_wave_out_id", cfg.WindowsWaveOutId, 0, winwavemax); - cfg.WindowsMidiInId = xmlcfg->getpar("windows_midi_in_id", + cfg.WindowsMidiInId = xmlcfg.getpar("windows_midi_in_id", cfg.WindowsMidiInId, 0, winmidimax); - xmlcfg->exitbranch(); + xmlcfg.exitbranch(); } - delete (xmlcfg); cfg.OscilSize = (int) pow(2, ceil(log(cfg.OscilSize - 1.0) / log(2.0))); } diff --git a/src/Misc/XMLwrapper.cpp b/src/Misc/XMLwrapper.cpp @@ -140,7 +140,7 @@ XMLwrapper::XMLwrapper() XMLwrapper::~XMLwrapper() { - if(tree != NULL) + if(tree) mxmlDelete(tree); } @@ -295,6 +295,13 @@ void XMLwrapper::endbranch() } +//workaround for memory leak +const char *trimLeadingWhite(const char *c) +{ + while(isspace(*c)) + ++c; + return c; +} /* LOAD XML members */ @@ -306,15 +313,14 @@ int XMLwrapper::loadXMLfile(const string &filename) const char *xmldata = doloadfile(filename.c_str()); if(xmldata == NULL) - return -1; //the file could not be loaded or uncompressed + return -1; //the file could not be loaded or uncompressed - root = tree = mxmlLoadString(NULL, xmldata, MXML_OPAQUE_CALLBACK); + root = tree = mxmlLoadString(NULL, trimLeadingWhite(xmldata), MXML_OPAQUE_CALLBACK); - delete [] xmldata; + delete[] xmldata; if(tree == NULL) - return -2; //this is not XML - + return -2; //this is not XML node = root = mxmlFindElement(tree, tree, @@ -323,7 +329,7 @@ int XMLwrapper::loadXMLfile(const string &filename) NULL, MXML_DESCEND); if(root == NULL) - return -3; //the XML doesnt embbed zynaddsubfx data + return -3; //the XML doesnt embbed zynaddsubfx data //fetch version information version.Major = stringTo<int>(mxmlElementGetAttr(root, "version-major")); @@ -335,7 +341,6 @@ int XMLwrapper::loadXMLfile(const string &filename) cout << "loadXMLfile() version: " << version.Major << '.' << version.Minor << '.' << version.Revision << endl; - return 0; } @@ -379,7 +384,7 @@ bool XMLwrapper::putXMLdata(const char *xmldata) if(xmldata == NULL) return false; - root = tree = mxmlLoadString(NULL, xmldata, MXML_OPAQUE_CALLBACK); + root = tree = mxmlLoadString(NULL, trimLeadingWhite(xmldata), MXML_OPAQUE_CALLBACK); if(tree == NULL) return false; diff --git a/src/Tests/XMLwrapperTest.h b/src/Tests/XMLwrapperTest.h @@ -21,6 +21,8 @@ */ #include <cxxtest/TestSuite.h> #include "../Misc/XMLwrapper.h" +#include <string> +using namespace std; class XMLwrapperTest:public CxxTest::TestSuite { @@ -36,6 +38,24 @@ class XMLwrapperTest:public CxxTest::TestSuite TS_ASSERT_EQUALS(xmla->getpar("my Pa*_ramet@er", 0, -200, 200), 75); } + //here to verify that no leaks occur + void testLoad() { + string location = string(SOURCE_DIR) + string("/Tests/guitar-adnote.xmz"); + xmla->loadXMLfile(location); + } + + void testAnotherLoad() + { + string dat = "\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ +<!DOCTYPE ZynAddSubFX-data>\n\ +<ZynAddSubFX-data version-major=\"2\" version-minor=\"4\"\n\ +version-revision=\"1\" ZynAddSubFX-author=\"Nasca Octavian Paul\">\n\ +</ZynAddSubFX-data>\n"; + xmlb->putXMLdata(dat.c_str()); +#warning todo contact mxml people about possible memoryleak when +#warning mxmlLoadString is giving something starting with a newline + } + void tearDown() { delete xmla; delete xmlb;