Jump to content
  • Advertisement
Sign in to follow this  
Koshmaar

Bug in SDL_RWops?

This topic is 4854 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, I have "little" problem with SDL_RWops. If you don't know what's this, I tell you: it's part of SDL responsible for abstracting reading/writing operations on various streams (ie. file, memory). Wiki is here and here. As to my problem - you see, I'm trying to load config file (which is normal text file) line by line (cause it's the way parser is working) from SDL_RWops source. That source is created using this code, borrowed from SDL_Image: SDL_RWops *source = SDL_RWFromFile(filename.c_str(), "r"); Since lines can be of any sizes (could be 10, 1024 or 1, no limits), I need a way to determine where are '\n' located. That way, I can dynamically mallocate enough memory and fill it with all characters up to '\n' - which will be passed to parser, then we deallocate that memory, move to next line and so on. Seeking for char inside SDL_RWops is performed by this "little" function. I know it's far from perfect, but it *should* be working - however, output I get from stderr shows that it isn't, and I suspect nasty bug in SDL_RWread() or SDL_RWtell().

#define CFG_DEBUG(x, y) fprintf(stderr, x, y);

// returns size of line to create, counting from current read-ptr position
//  xxx -char we're looking for
int SDL_RWfind( SDL_RWops * source, char xxx, int * last_line_length)
 {
  const int buffer_size = 512;

  // we're reading up to buffer_size characters to this buffer
  char buffer [buffer_size];
  
  // number of bytes read during last SDL_RWread()
  int read;

 // number of bytes that were read up to now
  int read_all = 0;
  char * buffer_ptr;
  
  do
   {

    // -------------------------------- start of the most important part !

    // get current offset (before reading)
    CFG_DEBUG("\nSDL_RWfind: Current offset before RWread: %i.\n", SDL_RWtell(source));

    // according to SDL Wiki, SDL_RWread: "It returns the number of memory blocks read"
    // and here blocks have size of 1 - so it should return the number of characters read
    read = SDL_RWread(source, buffer, 1, buffer_size ); 
    
    CFG_DEBUG("SDL_RWfind: Read characters: %i.\n", read);
    
    // get current offset (after reading)
    CFG_DEBUG("\nSDL_RWfind: Current offset after RWread: %i.\n", SDL_RWtell(source));

    // -------------------------------- end of the most important part,  next lines of this function were added just for completness sake


    if (read < 0) { CFG_DEBUG("Couldn't read even one block from stream while seeking: %c.\n", xxx); return -2; }
    
    buffer_ptr = buffer;
    read_all += read;

    while ( (buffer_ptr - buffer) < read )
     { 
      if ( (*buffer_ptr) == xxx) // we've found it
       {     
        SDL_RWseek(source, -read_all, SEEK_CUR);
        return ( buffer_ptr - buffer);
       }
       
     ++buffer_ptr;
    }
     
  } while ( read == buffer_size );

  *last_line_length = read_all; 
  SDL_RWseek(source, -read_all - 1 , SEEK_CUR);
  return -1;
 }



And now, most important part of this mail: After using that function for this file:
bad_integer = 1234
good_integer = 1234


... I get in stderr this:

1) SDL_RWfind: Current offset before RWread: 0.
2) SDL_RWfind: Read characters: 41.
3) SDL_RWfind: Current offset after RWread: 45.



Do you see what's going on? We have read 41 characters (line 2) starting from offset 0 (line 1), so we should be at position 41, right? But line 3 says that we're at position 45!!!! And as you can see, there weren't ANY reading / writing / seeking etc. going on! The only logic I could see after this behaviour: whole file has size of 45 bytes. But that shouldn't change anything... If someone could tell me whether this is SDL_RWops bug, it's my code's failure, or has working function for finding char in SDL_RWops stream or sth similiar, I would be really gratefull for sharing it with me ( you know, ++rating etc. ;-) )

Share this post


Link to post
Share on other sites
Advertisement
You're right, I remember from SDL mailinglist that there were thread about possible bug in SDL_RWops, that has been fixed in CVS - what a shame I can't google it up now :-/

(after a minute)

Ok, I've found it :-) it's here: http://www.devolution.com/pipermail/sdl/2005-May/068922.html.

and quoting part:

Quote:

SDL_RWops changes

Bugs:
-Reading from memory was not consistant with how reading from files worked.
A file of 55 bytes stored into 'ptr' by using 6 sets of 10 bytes would copy
55 bytes into 'ptr' and SDL_RWread would return 5. But the same act done on
mem RWop would result in 50 bytes copied and 5 returned.

-Seems that SDL_RWclose should return fclose's return value instead of 0

-Since there is no feof or ferror wrappers... if read or write return less
than requested... it was not known why. Added SDL_RWeof, SDL_RWerror, and
SDL_RWclearerr

-mem_writeconst() would return a -1... but fwrite nor mem_write would return
a -1 on an error... especially since the concept of knowing an error occured
didnt exist... return 0 now and sets flags as error.

-since it is obvious RWops is based off stdio FILE's... it would make sense
to use the same data types.
> ftell returns a long... RWseek returns ftell so RWseek returns long
> seek's offset argument is now a long
> read and write take size_t's instead of int's and return size_t's

-where RWop was free'd in RWclose functions... appears it should have been
using SDL_FreeRW since RWFromX's use SDL_AllocRW

-In unix_to_mac function... called from SDL_RWFromFile with a
const char* file = NULL would try to strlen(NULL)

-No check on the malloc used in unix_to_mac... put in check.

-mem_read and mem_write didnt check for overflows the same way fread/fwrite
do (at least how dietlibc impliments them)... if num or size are 0
return 0... if ((num * size) / num) != size) return 0

Misc:
-Fixed some comments in SDL_rwops.h

-renamed a few arguments for consistancy

-SDL_RWops.type is completely unused... removed.

-SDL_RWops.unknown also unused... removed.

-Added SDL_OutOfMemory error setting to any malloc's

-unknown values for 'whence' now also set RWerror

Enhancements:
-Added the concept of SDL_RWeof, SDL_RWerror, and SDL_RWclearerr

-Created SDL_RWFromMallocedMem(void* ptr, size_t size)
If 'ptr' is NULL... it allocates 'size' bytes for you, otherwise
'ptr' must be from standard malloc. If you attempt to write past the
end of the buffer it will realloc the buffer. You may also treat it
like a file stream works... you can seek past the actual end and
when you attempt to write data it will realloc and copy the data. Area
between the original end and the seeked position will contain '\0''s
just as a write performed on a file which was seeked past it's end.
If realloc fails the buffer stays the same and the error flag is set.




First entry in Bugs section looks somewhat similiar (reading from file stream, wrong values) and that's probably what happened to my code.


I think I could build SDL from CVS on my own... but that's the last thing I would like to do, since it would take (too) much time and made some not-trivial changes to my coding enviroment. And knowing that last version of SDL was released more than half a year ago, and it's time for 1.2.9 now...


So, do you see any way to work-around this bug? Yes, I want to hack it, but I don't know exactly what is causing it. Any thoughts? Thx for help :-)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!