jgaeddert / liquid-dsp

digital signal processing library for software-defined radios
http://liquidsdr.org
MIT License
1.89k stars 442 forks source link

Memory leak in ofdmflexframe #99

Closed FarshadKoohifar closed 7 years ago

FarshadKoohifar commented 7 years ago

I am using this code to generate a lot of frames with different modulation and coding schemes. I noticed that the ofdmflexframe api is leaking memory in the process: `

include

include

include

include

include <liquid/liquid.h>

include

// options const unsigned int M = 64; // number of subcarriers const unsigned int cp_len = 16; // cyclic prefix length const unsigned int taper_len = 4; // taper length const unsigned int payload_len = 64; // length of payload (bytes) const unsigned int symbol_len = M + cp_len; // samples per OFDM symbol std::complex buffer[symbol_len]; // time-domain buffer unsigned char header[8]; // header unsigned char payload[payload_len]; // payload const int instantCount=1000; const int minSnr=-3; const int maxSnr=30; const int numModulations=5;

// global book keeping int detectedFrames; int errorBits; int errorBlocks; int errorHeader; int samplesPerFrame;

// Function that return count of // flipped number int FlippedCount(unsigned char a, unsigned char b){ unsigned char n=a^b; int count = 0; while (n){ count += n & 1; n >>= 1; } return count; }

// callback function int mycallback(unsigned char _header,int _header_valid,unsigned char _payload,unsigned int _payload_len,int _payload_valid,framesyncstats_s _stats,void _userdata){ if (!_header_valid){ errorHeader++; } detectedFrames++; for (unsigned int i=0;i<_payload_len;i++){ errorBits+=FlippedCount(_payload[i],payload[i]); } if(!_payload_valid){ errorBlocks++; } return 0; } struct scenario {modulation_scheme ms;fec_scheme fec1;}; int main() { FILE fp; fp = fopen ("simulationResults.txt", "w+"); const modulation_scheme myModulations[numModulations]={ LIQUID_MODEM_BPSK, LIQUID_MODEM_QAM4, LIQUID_MODEM_QAM16, LIQUID_MODEM_QAM64, LIQUID_MODEM_QAM256}; const int numFecs=18; fec_scheme myFecs[numFecs]={LIQUID_FEC_NONE, // no error-correction // codecs not defined internally (see http://www.ka9q.net/code/fec/) LIQUID_FEC_CONV_V27, // r1/2, K=7, dfree=10 LIQUID_FEC_CONV_V29, // r1/2, K=9, dfree=12 LIQUID_FEC_CONV_V39, // r1/3, K=9, dfree=18 LIQUID_FEC_CONV_V615, // r1/6, K=15, dfree<=57 (Heller 1968)

        // punctured (perforated) codes
        LIQUID_FEC_CONV_V27P23,     // r2/3, K=7, dfree=6
        LIQUID_FEC_CONV_V27P34,     // r3/4, K=7, dfree=5
        LIQUID_FEC_CONV_V27P45,     // r4/5, K=7, dfree=4
        LIQUID_FEC_CONV_V27P56,     // r5/6, K=7, dfree=4
        LIQUID_FEC_CONV_V27P67,     // r6/7, K=7, dfree=3
        LIQUID_FEC_CONV_V27P78,     // r7/8, K=7, dfree=3

        LIQUID_FEC_CONV_V29P23,     // r2/3, K=9, dfree=7
        LIQUID_FEC_CONV_V29P34,     // r3/4, K=9, dfree=6
        LIQUID_FEC_CONV_V29P45,     // r4/5, K=9, dfree=5
        LIQUID_FEC_CONV_V29P56,     // r5/6, K=9, dfree=5
        LIQUID_FEC_CONV_V29P67,     // r6/7, K=9, dfree=4
        LIQUID_FEC_CONV_V29P78,     // r7/8, K=9, dfree=4

        // Reed-Solomon codes
        LIQUID_FEC_RS_M8};
int totalLoops=instantCount*(maxSnr-minSnr)*numModulations*numFecs;
const std::complex<float> myI(0, 1);
// initialize header/payload and assemble frame
for (int i=0; i<8; i++)           header[i]  = i      & 0xff;
for (unsigned int i=0; i<payload_len; i++) payload[i] = rand() & 0xff;
int loopCounter=0;
for (int fecIter=3;fecIter<6;fecIter++){
    for(int modulationIter=0;modulationIter<numModulations;modulationIter++){
        for (float SNRdB=minSnr;SNRdB<maxSnr;SNRdB++){
            detectedFrames=0;
            errorBits=0;
            errorBlocks=0;
            errorHeader=0;
            for (int instant =0;instant<instantCount;instant++){
                samplesPerFrame=0;
                modulation_scheme ms = myModulations[modulationIter];   // payload modulation scheme
                fec_scheme fec0  = LIQUID_FEC_NONE;         // inner FEC scheme
                fec_scheme fec1  = myFecs[fecIter];   // outer FEC scheme
                crc_scheme check = LIQUID_CRC_32;           // data validity check
                float dphi  = 0.001f;                       // carrier frequency offset
                // create frame generator with default properties
                ofdmflexframegen fg =
                    ofdmflexframegen_create(M, cp_len, taper_len, NULL, NULL);
                // create frame synchronizer
                ofdmflexframesync fs =
                    ofdmflexframesync_create(M, cp_len, taper_len, NULL, mycallback, NULL);
                // re-configure frame generator with different properties
                ofdmflexframegenprops_s fgprops;
                ofdmflexframegen_getprops(fg,&fgprops); // query the current properties
                fgprops.check           = check;        // set the error-detection scheme
                fgprops.fec0            = fec0;         // set the inner FEC scheme
                fgprops.fec1            = fec1;         // set the outer FEC scheme
                fgprops.mod_scheme      = ms;           // set the modulation scheme
                ofdmflexframegen_setprops(fg,&fgprops); // reconfigure the frame generator
                ofdmflexframegen_assemble(fg, header, payload, payload_len);
                // channel parameters
                float nstd = powf(10.0f, -SNRdB/20.0f); // noise standard deviation
                float phi = 1.0f;                       // channel phase
                // generate frame and synchronize
                int last_symbol=0;
                while (!last_symbol) {
                    // generate symbol (write samples to buffer)
                    last_symbol = ofdmflexframegen_writesymbol(fg, buffer);
                    samplesPerFrame+=symbol_len;
                    // channel impairments
                    for (unsigned int i=0; i<symbol_len; i++) {
                        //buffer[i] *= std::exp(myI*phi); // apply carrier offset
                        //phi += dphi;                        // update carrier phase
                        cawgn(&buffer[i], nstd);            // add noise
                    }
                    // receive symbol (read samples from buffer)
                    ofdmflexframesync_execute(fs, buffer, symbol_len);
                }
                // destroy objects and return
                ofdmflexframegen_destroy(fg);
                ofdmflexframesync_destroy(fs);
            }
            printf("%.4f percent complete.\n",(float)100.0f*loopCounter/totalLoops);
            printf(" fecIter: %d\t modulationIter: %d\t SNRdB: %f\t bitPerSample: %f\t pFrameDetection: %f\t birErrorRate: %f\t blockErrorRate: %f\t headerErrorRate: %f\n", fecIter, modulationIter, SNRdB, (float)payload_len*8/samplesPerFrame,(float)detectedFrames/instantCount,(float)errorBits/(payload_len*8*instantCount),(float)errorBlocks/instantCount,(float)errorHeader/instantCount);
            fprintf(fp, "%d, %d, %f, %f, %f, %f, %f, %f\n", fecIter, modulationIter, SNRdB, (float)payload_len*8/samplesPerFrame, (float)detectedFrames/instantCount, (float)errorBits/(payload_len*8*instantCount), (float)errorBlocks/instantCount,(float)errorHeader/instantCount);
        }
    }
}
fclose(fp);
printf("done.\n");
return (0);

}

`

brian-armstrong commented 7 years ago

this code doesn't compile under liquid 1.3.0. have you tried upgrading?

FarshadKoohifar commented 7 years ago

Thanks Brian. The truth is, I have tried to upgrade, but could not!

I am running 1.2.0 and the code is basically a direct copy and paste from the tutorial. On README.md, there are two ways to install. The git clone way fails to ./bootstrap.sh with this:

./bootstrap.sh: 30: ./bootstrap.sh: aclocal: not found ./bootstrap.sh: 31: ./bootstrap.sh: autoconf: not found ./bootstrap.sh: 32: ./bootstrap.sh: autoheader: not found

Tarball link is broken, so I cannot try to bypass bootstrap.

brian-armstrong commented 7 years ago

Are you on linux? What happens if you run sudo apt-get install automake?

jgaeddert commented 7 years ago

Farshad, I can try to help you upgrade to 1.3.0. There was a memory leak that was fixed with this version that I can confirm does NOT exist with 1.3.0 using valgrind.

FarshadKoohifar commented 7 years ago

Thanks a lot Joseph and Brian! I have upgraded and confirmed that the issue is resolved.