 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
sakya
Joined: 28 Apr 2006 Posts: 190
|
Posted: Tue Jan 15, 2008 6:41 pm Post subject: [SOLVED] Memory leak in libTremor? |
|
|
Hi! :)
I'm experiencing some strange memory leak with libTremor.
This code just opens and closes an OGG Vorbis file and it leaks at least 4kb of memory.
I think I'm clearing all the memory I use: clear the OggVorbis_File variable and close the file (this should be closed by libTremor, but I tried also to close it in my code).
Can someone help me find this leak, or test this code to be sure it's not related to my dev env?
Many thanks. :)
| Code: | /////////////////////////////////////////////////////////////////////////////////////////
//Callback for vorbis
/////////////////////////////////////////////////////////////////////////////////////////
size_t ogg_callback_read(void *ptr, size_t size, size_t nmemb, void *datasource){
return sceIoRead(*(int *) datasource, ptr, size * nmemb);
}
int ogg_callback_seek(void *datasource, ogg_int64_t offset, int whence){
return sceIoLseek32(*(int *) datasource, (unsigned int) offset, whence);
}
long ogg_callback_tell(void *datasource){
return sceIoLseek32(*(int *) datasource, 0, SEEK_CUR);
}
int ogg_callback_close(void *datasource){
return sceIoClose(*(int *) datasource);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Open/close an OGG file
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int openCloseOGG(char *filename){
int tempFile = 0;
OggVorbis_File vf;
//Apro il file OGG:
tempFile = sceIoOpen(filename, PSP_O_RDONLY, 0777);
if (tempFile >= 0) {
ov_callbacks ogg_callbacks;
ogg_callbacks.read_func = ogg_callback_read;
ogg_callbacks.seek_func = ogg_callback_seek;
ogg_callbacks.close_func = ogg_callback_close;
ogg_callbacks.tell_func = ogg_callback_tell;
if (ov_open_callbacks(&tempFile, &vf, NULL, 0, ogg_callbacks) < 0){
sceIoClose(tempFile);
return -1;
}
ov_clear(&vf);
if (tempFile >= 0)
sceIoClose(tempFile);
}
return 0;
} |
I can post the full code if needed (tha main just executes openCloseOGG when pressing X and check freemem). ;)
Ciaooo
Sakya
Last edited by sakya on Fri Jan 18, 2008 3:44 am; edited 1 time in total |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Wed Jan 16, 2008 11:50 am Post subject: |
|
|
| Does it leak every time you call it, or just the FIRST time? Every time would be a leak. Only the first time is just the system needed to use some resources that don't get flushed until you exit. |
|
| Back to top |
|
 |
sakya
Joined: 28 Apr 2006 Posts: 190
|
Posted: Wed Jan 16, 2008 4:53 pm Post subject: |
|
|
Hi! :)
| J.F. wrote: | | Does it leak every time you call it, or just the FIRST time? Every time would be a leak. Only the first time is just the system needed to use some resources that don't get flushed until you exit. |
Many thanks for your reply. ;)
It leaks 4kb (sometimes 8) every time I call the function.
I tried also with ov_open instead of ov_open_callbacks but the result is the same.
Ciaooo
Sakya |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Wed Jan 16, 2008 5:15 pm Post subject: |
|
|
Well, the libTremor docs say this:
| Quote: | | Once the file is no longer needed, ov_clear() is used to close the file and deallocate decoding resources. Do not call fclose() on the file; libvorbisidec does this in the ov_clear() call. |
And in vorbisfile.c, you find this at the end of the ov_clear function:
| Code: | if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
memset(vf,0,sizeof(*vf));
|
What happens if you don't do the second sceIoClose()? Perhaps the leak is due to trying to close the file twice. |
|
| Back to top |
|
 |
sakya
Joined: 28 Apr 2006 Posts: 190
|
Posted: Wed Jan 16, 2008 6:21 pm Post subject: |
|
|
Hi! :)
| J.F. wrote: | | What happens if you don't do the second sceIoClose()? Perhaps the leak is due to trying to close the file twice. |
The same thing. I added the additional close to try to solve the leak...
Here's the full source I'm using:
| Code: | #include <pspkernel.h>
#include <pspctrl.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <stdlib.h>
#include "tremor/ivorbiscodec.h"
#include "tremor/ivorbisfile.h"
PSP_MODULE_INFO("eboot template", 0, 1, 0);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER);
PSP_HEAP_SIZE_KB(2048);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Globals:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int runningFlag = 1;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Callbacks:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common) {
runningFlag = 0;
return 0;
}
/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0);
if(thid >= 0)
sceKernelStartThread(thid, 0, 0);
return thid;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Total free memory:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct
{
void *buffer;
void *next;
} _LINK;
int freemem(){
int size = 4096, total = 0;
_LINK *first = NULL, *current = NULL, *lnk;
while(runningFlag){
lnk = (_LINK*)malloc(sizeof(_LINK));
if (!lnk)
break;
total += sizeof(_LINK);
lnk->buffer = malloc(size);
if (!lnk->buffer){
free(lnk);
break;
}
total += size;
lnk->next = NULL;
if (current){
current->next = (void*)lnk;
current = lnk;
} else {
current = first = lnk;
}
}
lnk = first;
while (lnk){
free(lnk->buffer);
current = lnk->next;
free(lnk);
lnk = current;
}
return total;
}
/////////////////////////////////////////////////////////////////////////////////////////
//Callback for vorbis
/////////////////////////////////////////////////////////////////////////////////////////
size_t ogg_callback_read(void *ptr, size_t size, size_t nmemb, void *datasource){
return sceIoRead(*(int *) datasource, ptr, size * nmemb);
}
int ogg_callback_seek(void *datasource, ogg_int64_t offset, int whence){
return sceIoLseek32(*(int *) datasource, (unsigned int) offset, whence);
}
long ogg_callback_tell(void *datasource){
return sceIoLseek32(*(int *) datasource, 0, SEEK_CUR);
}
int ogg_callback_close(void *datasource){
return sceIoClose(*(int *) datasource);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Open/close an OGG file
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int openCloseOGG(char *filename){
int tempFile = 0;
OggVorbis_File vf;
//Apro il file OGG:
tempFile = sceIoOpen(filename, PSP_O_RDONLY, 0777);
if (tempFile >= 0) {
ov_callbacks ogg_callbacks;
ogg_callbacks.read_func = ogg_callback_read;
ogg_callbacks.seek_func = ogg_callback_seek;
ogg_callbacks.close_func = ogg_callback_close;
ogg_callbacks.tell_func = ogg_callback_tell;
if (ov_open_callbacks(&tempFile, &vf, NULL, 0, ogg_callbacks) < 0){
sceIoClose(tempFile);
return -1;
}
ov_clear(&vf);
}
return 0;
}
int openCloseOGGNoCallbacks(char *filename){
FILE *tempFile;
OggVorbis_File vf;
//Apro il file OGG:
tempFile = fopen(filename, "r");
if (tempFile != NULL) {
if (ov_open(tempFile, &vf, NULL, 0) < 0){
fclose(tempFile);
return -1;
}
ov_clear(&vf);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(){
pspDebugScreenInit();
SetupCallbacks();
pspDebugScreenPrintf("Test OGG Vorbis mem. leak\n\n");
pspDebugScreenPrintf("Free memory: %i\n", freemem() / 1024);
pspDebugScreenPrintf("Press X to load and unload with callbacks ms0:/test.ogg\n");
pspDebugScreenPrintf("Press SQUARE to load and unload without callbacks ms0:/test.ogg\n");
SceCtrlData pad;
while(runningFlag){
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS){
pspDebugScreenPrintf("Open result: %i\n", openCloseOGG("ms0:/test.ogg"));
pspDebugScreenPrintf("Free memory: %i\n", freemem() / 1024);
sceKernelDelayThread(200000);
}else if (pad.Buttons & PSP_CTRL_SQUARE){
pspDebugScreenPrintf("Open result: %i\n", openCloseOGGNoCallbacks("ms0:/test.ogg"));
pspDebugScreenPrintf("Free memory: %i\n", freemem() / 1024);
sceKernelDelayThread(200000);
}
}
sceKernelExitGame();
return 0;
} |
Ciaooo
Sakya |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Thu Jan 17, 2008 5:46 am Post subject: |
|
|
Okay, maybe this is the problem... look at the one line in ov_clear again:
| Code: | | if(vf->datasource)(vf->callbacks.close_func)(vf->datasource); |
It closes the file if the file is there. However, in your second close function, you check if the file handle is >= 0, If it can be 0, the ov_clear line won't be called as vf->datasource is 0. It assumes file handles cannot be 0.
Print out the handle to see what it is. If it really is 0, you'll need to make some kind of indirection on it and the callbacks to get it to work right. |
|
| Back to top |
|
 |
sakya
Joined: 28 Apr 2006 Posts: 190
|
Posted: Thu Jan 17, 2008 8:29 am Post subject: |
|
|
Hi! :)
| J.F. wrote: | | It closes the file if the file is there. However, in your second close function, you check if the file handle is >= 0, If it can be 0, the ov_clear line won't be called as vf->datasource is 0. |
Many thanks for helping. :)
No luck, I displayed the value but it's 3 with fopen and a bigger number with sceIoOpen but never zero.
Ciaooo
Sakya |
|
| Back to top |
|
 |
jimparis
Joined: 10 Jun 2005 Posts: 1179 Location: Boston
|
Posted: Thu Jan 17, 2008 10:48 am Post subject: |
|
|
I updated libTremor to the latest xiph SVN. In my quick tests on the PC, the old version had a memory leak and the new version does not. Give it a try.
Here was the leak:
| Code: | ==12544== 208 bytes in 2 blocks are definitely lost in loss record 2 of 5
==12544== at 0x4C20F3F: calloc (vg_replace_malloc.c:279)
==12544== by 0x4E34511: ogg_stream_create (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E2FA1F: _ov_open1 (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E2FB33: ov_open_callbacks (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E2FB9B: ov_open (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x400680: main (in /tmp/examples/ivorbisfile_example)
==12544==
==12544==
==12544== 5,536 (32 direct, 5,504 indirect) bytes in 1 blocks are definitely lost in loss record 5 of 5
==12544== at 0x4C21C16: malloc (vg_replace_malloc.c:149)
==12544== by 0x4E33E52: _fetch_ref (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E33F1D: ogg_buffer_split (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E347F8: ogg_sync_pageseek (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E2D854: _get_next_page (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E2DAEE: _fetch_headers (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E2FA3D: _ov_open1 (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E2FB33: ov_open_callbacks (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x4E2FB9B: ov_open (in /usr/local/lib/libvorbisidec.so.1.0.2)
==12544== by 0x400680: main (in /tmp/examples/ivorbisfile_example)
|
|
|
| Back to top |
|
 |
sakya
Joined: 28 Apr 2006 Posts: 190
|
Posted: Thu Jan 17, 2008 8:36 pm Post subject: |
|
|
Hi! :)
| jimparis wrote: | | I updated libTremor to the latest xiph SVN. In my quick tests on the PC, the old version had a memory leak and the new version does not. Give it a try. |
So it's true! Many thanks! :)
Can you help me please to compile the new version for psp?
I tried downloading the new source code from xiph svn and then launched:
| Code: | $ LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./autogen.sh \
--host psp --prefix=$(psp-config --psp-prefix)
$ make |
But I get this error during compilation:
| Code: | make all-am
make[1]: Entering directory `/home/user/libTremor_new'
if /bin/sh ./libtool --tag=CC --mode=compile psp-gcc -DHAVE_CONFIG_H -I. -I. -I.
-I./ -O2 -Wall -fsigned-char -D_REENTRANT -MT mdct.lo -MD -MP -MF ".deps/md
ct.Tpo" -c -o mdct.lo mdct.c; \
then mv -f ".deps/mdct.Tpo" ".deps/mdct.Plo"; else rm -f ".deps/mdct.Tpo
"; exit 1; fi
psp-gcc -DHAVE_CONFIG_H -I. -I. -I. -I./ -O2 -Wall -fsigned-char -D_REENTRANT -
MT mdct.lo -MD -MP -MF .deps/mdct.Tpo -c mdct.c -o mdct.o
In file included from mdct.c:37:
misc.h:47: error: redefinition of 'union magic'
make[1]: *** [mdct.lo] Error 1
make[1]: Leaving directory `/home/user/libTremor_new'
make: *** [all] Error 2 |
Many thanks again. ;)
Ciaooo
Sakya |
|
| Back to top |
|
 |
jimparis
Joined: 10 Jun 2005 Posts: 1179 Location: Boston
|
Posted: Fri Jan 18, 2008 1:33 am Post subject: |
|
|
Don't download it from xiph svn, download it from pspdev svn. Or just rerun the psplibraries script.
When I say I updated it, I mean I updated the pspdev version. |
|
| Back to top |
|
 |
sakya
Joined: 28 Apr 2006 Posts: 190
|
Posted: Fri Jan 18, 2008 1:36 am Post subject: |
|
|
Hi! :)
| jimparis wrote: | Don't download it from xiph svn, download it from pspdev svn.
When I say I updated it, I mean I updated the pspdev version. |
Oh, sorry. O:)
Many thanks, really. :)
I'll try this evening (this damned proxy doesen't allow me to connect to svn).
Ciaooo
Sakya |
|
| Back to top |
|
 |
jimparis
Joined: 10 Jun 2005 Posts: 1179 Location: Boston
|
|
| Back to top |
|
 |
sakya
Joined: 28 Apr 2006 Posts: 190
|
Posted: Fri Jan 18, 2008 3:44 am Post subject: |
|
|
Hi! :)
The damned proxy blocked also this connection (cannot connect to server) but I downloaded the new version now and the memory leak is gone! :)
Many thanks again.
Ciaooo
Sakya |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Fri Jan 18, 2008 6:28 am Post subject: |
|
|
| That's great news to anyone using libTremor on the PSP. Just updating the libraries and recompiling fixes a potential problem. :) |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|