forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Problems freeing memory

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
Archaemic



Joined: 18 Mar 2007
Posts: 38

PostPosted: Mon Mar 19, 2007 12:33 am    Post subject: Problems freeing memory Reply with quote

Most of the time when I free memory, my PSP is fine, but when I try to free two specific pieces of memory, it gives me a bus error ever single time. I've compiled the same code on Windows (with standard C or SDL system calls instead of PSP system calls) and it runs 100% fine (except for one segfault in portions of SDL's code, not mine. It doesn't crash the program, so I'm fine).

The memory allocation looks like this:

Code:
      book.page_order = malloc(sizeof(char*)*book.num_pages);
      int i;
      unzGoToFirstFile(book.zip_file);
      int status = UNZ_OK;
      for(i = 0; status == UNZ_OK; i++) {
         char *block = init_block(1);
         unzGetCurrentFileInfo(book.zip_file,NULL,block,1024,NULL,0,NULL,0);
         book.page_order[i] = block;
         status = unzGoToNextFile(book.zip_file);
      }


Where init_block is such:
Code:
inline char* init_block(Uint16 kb) {
   Uint32 loc, bytes = kb*1024;
   char* block = malloc(sizeof(char)*bytes);
   for(loc = 0; loc < bytes; loc++)
      block[loc] = 0;
   return block;
}

(I should put in a extra check, but...)

The freeing looks like this:
Code:
void close_comic_book(comic_book book) {
   if(book.type == comic_book_zip)
      unzClose(book.zip_file);
#   ifndef PSP
   int i;
   for(i = 0; i < book.num_pages; i++) {
      if(book.page_order[i] == NULL) {
         printf("Memory leak detected.");
         next_line();
      }
      else free(book.page_order[i]); //This is the line that crashes.
   }
#   endif
   free(book.page_order);
}

It crashes on the first iteration of the loop, so it's not a buffer overflow. Trying to free even the first item manually fails.

Is my init_block code buggy? Or could this be an error with PSPSDK?

Edit] Ah, I forgot to mention. The memory appears to get corrupted by the unzClose, but putting the free before the unzClose doesn't fix anything; it still crashes in the same place.

Code:
(gdb) print *book->page_order
$4 = 0x8a21500 "Deadpool 01/Deadpool - 001 00fc.jpg"
(gdb) print book->page_order[1]
$5 = 0x8a21910 "Deadpool 01/Deadpool - 001 01.jpg"
(gdb) until
471                     unzClose(book->zip_file);
(gdb) until
474             for(i = 0; i < book->num_pages; i++) {
(gdb) print book->page_order[1]
$6 = 0x8a21910 "Deadpool"
(gdb) print book->page_order[]
A syntax error in expression, near `]'.
(gdb) print book->page_order[0]
$7 = 0x8a21500 "Deadpool 01/\020\031¢\bpool - 001 00fc.jpg"
Back to top
View user's profile Send private message
StrmnNrmn



Joined: 14 Feb 2007
Posts: 46
Location: London, UK

PostPosted: Mon Mar 19, 2007 1:14 am    Post subject: Re: Problems freeing memory Reply with quote

Archaemic wrote:
Or could this be an error with PSPSDK?


Given how heavily used PSPSDK/zlib are used, is it's much more likely the error is somewhere in your code.

A couple of things you could try:

memset() book.page_order to 0 after allocation - from your code it looks like you may end up with uninitialised memory if unzGoToNextFile returns an error before you've filled in book.num_pages.

Are you using MSVC on Windows or GCC? You could try running with the debug CRT and setting _CRTDBG_CHECK_ALWAYS_DF (see MSDN here). This will warn you about heap corruption etc closer to the point of error.
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Archaemic



Joined: 18 Mar 2007
Posts: 38

PostPosted: Mon Mar 19, 2007 2:18 am    Post subject: Reply with quote

I'm pretty sure it's not PSPSDK too.

Anyway, you can still free uninitialized memory so long as you've allocated it, can't you? I can't imagine why could couldn't.

Also, I forgot to mention, I'm using minizip for the unz functions.

I have absolutely no clue why this is crashing, though. I tried compiling it without optimizations and it still crashes. It's really weird.
Back to top
View user's profile Send private message
StrmnNrmn



Joined: 14 Feb 2007
Posts: 46
Location: London, UK

PostPosted: Mon Mar 19, 2007 2:31 am    Post subject: Reply with quote

Archaemic wrote:
Anyway, you can still free uninitialized memory so long as you've allocated it, can't you? I can't imagine why could couldn't.


Freeing book.page_order when the contents are uninitialised is fine, but freeing book.page_order[i] will crash if it's not been initialised. In your initialisation loop, you won't initialise all the elements of book.page_order if unzGoToNextFile() returns an error.

So as an example, let's say book.num_pages is 5 and that unzGoToNextFile returns an error the second time it's called. Your book.page_order array will end up looking like this:

book.page_order[0] = someptr;
book.page_order[1] = anotherptr;
book.page_order[2] = random_uninitialised_value1;
book.page_order[3] = random_uninitialised_value2;
book.page_order[4] = random_uninitialised_value3;

Code:

book.page_order = malloc(sizeof(char*)*book.num_pages);
memset(book.page_order, 0, sizeof(char*)*book.num_pages);
int i;
...
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
StrmnNrmn



Joined: 14 Feb 2007
Posts: 46
Location: London, UK

PostPosted: Mon Mar 19, 2007 2:35 am    Post subject: Reply with quote

One more thing - there's no check in your initialisation for-loop that i < book.num_pages. If there are more files in the zip than you've reserved entries for, you'll stomp all over the memory following book.page_order.

I can't see where you get book.num_pages from, but you might want to update the initialisation loop to look something like this:

Code:

      book.page_order = malloc(sizeof(char*)*book.num_pages);
      memset(book.page_order, 0, sizeof(char*)*book.num_pages);
      int i;
      unzGoToFirstFile(book.zip_file);
      int status = UNZ_OK;
      for(i = 0; i < book.num_pages; i++) {
         char *block = init_block(1);
         unzGetCurrentFileInfo(book.zip_file,NULL,block,1024,NULL,0,NULL,0);
         book.page_order[i] = block;
         status = unzGoToNextFile(book.zip_file);
         if(status != UNZ_OK)
            break;
      }
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Archaemic



Joined: 18 Mar 2007
Posts: 38

PostPosted: Mon Mar 19, 2007 3:10 am    Post subject: Reply with quote

book.num_pages is obtained by running through the zip file once to find out exactly how many pages there are (not all files in the zip are pages!). Not exactly the most efficient way, but it's the only way I can think of.

And as I said, even freeing the first one crashes the program.

Just for reference, the whole block looks like this now (and works under Windows):

Code:
      book.type = comic_book_zip;
      book.zip_file = unzOpen(filename);
      if(book.zip_file == NULL) {
         printf("Error opening file.");
         next_line();
         unzClose(book.zip_file);
         book.zip_file = NULL;
         return book;
      }
      int status = UNZ_OK;
      do {
         char *block = init_block(1);
         unzGetCurrentFileInfo(book.zip_file,NULL,block,1024,NULL,0,NULL,0);
         if(block[1023] != 0) {
            printf("Filename in zip too long.");
            next_line();
            unzClose(book.zip_file);
            book.zip_file = NULL;
            free(block);
            return book;
         }
         if((ends_with(block,".jpg") > 0) || (ends_with(block,".jpeg") > 0) ||
           (ends_with(block,".png") > 0) || (ends_with(block,".tiff") > 0) ||
           (ends_with(block,".bmp") > 0) || (ends_with(block,".gif") > 0))
            book.num_pages++;
         free(block);
      } while((status = unzGoToNextFile(book.zip_file)) == UNZ_OK);
      if(status != UNZ_END_OF_LIST_OF_FILE) {
         printf("Error reading zip.");
         next_line();
         unzClose(book.zip_file);
         book.zip_file = NULL;
         return book;
      } else if(book.num_pages < 1) {
         printf("Book is empty.");
         next_line();
         unzClose(book.zip_file);
         book.zip_file = NULL;
         return book;
      }
      book.page_order = malloc(sizeof(char*)*book.num_pages);
      memset(book.page_order,0,book.num_pages*sizeof(char*));
      int i;
      unzGoToFirstFile(book.zip_file);
      status = UNZ_OK;
      for(i = 0; (status == UNZ_OK) && (i < book.num_pages); i++) {
         char *block = init_block(1);
         unzGetCurrentFileInfo(book.zip_file,NULL,block,1024,NULL,0,NULL,0);
         book.page_order[i] = block;
         status = unzGoToNextFile(book.zip_file);
      }
      unzGoToFirstFile(book.zip_file);


I'm also having problems with SDL filling the whole screen when running on the PSP. It's weird. It only writes to the top-left pixel. I think I have some serious memory corruption going on here.

Also, it only does this sometimes. Mostly when I program something wrong. But the calls stay the same. Really weird. This doesn't happen when I compile -O0 (although the crashing still does). psp-gdb just isn't helping me.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
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