SDL_RWread Inconsistency

Dear Sir/Madam,

I encountered an intermittent issue when using SDL_RWread. Sometimes, things work and sometimes additional funny characters are added in. (Same program without rebuild).

Can anyone have a guess why that happens and how do I resolve it?

Thank You

my code is

    _file_ = SDL_RWFromFile(_path_.c_str(), "r");
    if (_file_!=NULL) {
        Uint8 buf[256];
        size_t bytesRead;

        do {
            bytesRead = SDL_RWread(_file_, buf, sizeof(Uint8), 256);

            // clear unused buf 
            for(int i=bytesRead; i<256; i++) {
                buf[i] = ' ';
            }
            std::cout << buf; 
           //_fileContents_ is a stingStream
            _fileContents_ << buf;
        } while (bytesRead>=256);

        SDL_RWclose(_file_);

        std::cout << "\n\n\n\n\njson is \n" << _fileContents_.str() << std::endl; 

Correct json (when did not fail)

{
    /*
        Logs
    */
    "logs" : [ 
                // logs.txt
                /*
                    It is recommended that you put all the logs files in use here so that the logs files will be initialized upon the start
                    and any error will be thrown. For logs files, error will be thrown to std error and program terminated

                    The first log will be the default log.
                */
                { 
                    // The minimum level to start printing to log file. 1 - DEBUG, 2 - INFO, 3 - ERROR, 4 - FATAL
                    // Thus if it is 2 (INFO), all DEBUG level will not be printed to the log
                    "loggingLevel" : 1, 
                    // the mode to open the file. must be one of the below
                    // "a", "a+", "w", "w+", "r+"  
                    // read SDL_RWFromFile for more info
                    "mode" : "w",
                    // the log file name
                    "fileName" : "logs.txt"
                }
    ]
}                                                                                                                                                                                                                                                          




json is 
{
    /*
        Logs
    */
    "logs" : [ 
                // logs.txt
                /*
                    It is recommended that you put all the logs files in use here so that the logs files will be initialized upon the start
                    and any error will be thrown. For logs files, error will be thrown to std error and program terminated

                    The first log will be the default log.
                */
                { 
                    // The minimum level to start printing to log file. 1 - DEBUG, 2 - INFO, 3 - ERROR, 4 - FATAL
                    // Thus if it is 2 (INFO), all DEBUG level will not be printed to the log
                    "loggingLevel" : 1, 
                    // the mode to open the file. must be one of the below
                    // "a", "a+", "w", "w+", "r+"  
                    // read SDL_RWFromFile for more info
                    "mode" : "w",
                    // the log file name
                    "fileName" : "logs.txt"
                }
    ]
}                                                                                                                                                                                                            

Incorrect json attempt 1

{
    /*
        Logs
    */
    "logs" : [ 
                // logs.txt
                /*
                    It is recommended that you put all the logs files in use here so that the logs files will be initialized upon the start
                    and @u�any error will be thrown. For logs files, error will be thrown to std error and program terminated

                    The first log will be the default log.
                */
                { 
                    // The minimum level to start printing @u�to log file. 1 - DEBUG, 2 - INFO, 3 - ERROR, 4 - FATAL
                    // Thus if it is 2 (INFO), all DEBUG level will not be printed to the log
                    "loggingLevel" : 1, 
                    // the mode to open the file. must be one of t@u�he below
                    // "a", "a+", "w", "w+", "r+"  
                    // read SDL_RWFromFile for more info
                    "mode" : "w",
                    // the log file name
                    "fileName" : "logs.txt"
                }
 @u�   ]
}                                                                                                                                                                                                                                                          @u�




json is 
{
    /*
        Logs
    */
    "logs" : [ 
                // logs.txt
                /*
                    It is recommended that you put all the logs files in use here so that the logs files will be initialized upon the start
                    and @u�any error will be thrown. For logs files, error will be thrown to std error and program terminated

                    The first log will be the default log.
                */
                { 
                    // The minimum level to start printing @u�to log file. 1 - DEBUG, 2 - INFO, 3 - ERROR, 4 - FATAL
                    // Thus if it is 2 (INFO), all DEBUG level will not be printed to the log
                    "loggingLevel" : 1, 
                    // the mode to open the file. must be one of t@u�he below
                    // "a", "a+", "w", "w+", "r+"  
                    // read SDL_RWFromFile for more info
                    "mode" : "w",
                    // the log file name
                    "fileName" : "logs.txt"
                }
 @u�   ]
}                                                                                                                                                                                                             

Incorrect json 2

{
    /*
        Logs
    */
    "logs" : [ 
                // logs.txt
                /*
                    It is recommended that you put all the logs files in use here so that the logs files will be initialized upon the start
                    and @��any error will be thrown. For logs files, error will be thrown to std error and program terminated

                    The first log will be the default log.
                */
                { 
                    // The minimum level to start printing @��to log file. 1 - DEBUG, 2 - INFO, 3 - ERROR, 4 - FATAL
                    // Thus if it is 2 (INFO), all DEBUG level will not be printed to the log
                    "loggingLevel" : 1, 
                    // the mode to open the file. must be one of t@��he below
                    // "a", "a+", "w", "w+", "r+"  
                    // read SDL_RWFromFile for more info
                    "mode" : "w",
                    // the log file name
                    "fileName" : "logs.txt"
                }
 @��   ]
}                                                                                                                                                                                                                                                          @��




json is 
{
    /*
        Logs
    */
    "logs" : [ 
                // logs.txt
                /*
                    It is recommended that you put all the logs files in use here so that the logs files will be initialized upon the start
                    and @��any error will be thrown. For logs files, error will be thrown to std error and program terminated

                    The first log will be the default log.
                */
                { 
                    // The minimum level to start printing @��to log file. 1 - DEBUG, 2 - INFO, 3 - ERROR, 4 - FATAL
                    // Thus if it is 2 (INFO), all DEBUG level will not be printed to the log
                    "loggingLevel" : 1, 
                    // the mode to open the file. must be one of t@��he below
                    // "a", "a+", "w", "w+", "r+"  
                    // read SDL_RWFromFile for more info
                    "mode" : "w",
                    // the log file name
                    "fileName" : "logs.txt"
                }
 @��   ]
}                                                                                                                                                                                                                                                          @��

You aren’t terminating buf anywhere, so whatever random bytes lie past the end of it are getting printed (and copied to _fileContents_) as well, until it reaches a zero in memory, which it’ll interpret as the null terminating character and stop. If you want to read from a text file 256 bytes at a time, buf needs to be 257 bytes in size, to have room for the null terminator.

Also, don’t clear buf to spaces, clear it to '\0' (the terminating character). And just use memset instead of a for loop.

    _file_ = SDL_RWFromFile(_path_.c_str(), "r");
    if (_file_!=NULL) {
        const size_t maxReadBytes = 256;
        char buf[maxReadBytes + 1];            // it's text, just make it a char
        size_t bytesRead;

        do {
            // clear buf
            // could use 0 instead of '\0', but '\0' is more explicit
            SDL_memset(&buf, '\0', sizeof(buf));    // sizeof(buf) == 257

            bytesRead = SDL_RWread(_file_, buf, sizeof(Uint8), maxReadBytes);

            std::cout << buf; 
           //_fileContents_ is a stingStream
            _fileContents_ << buf;
        } while (bytesRead>=maxReadBytes);

        SDL_RWclose(_file_);

        std::cout << "\n\n\n\n\njson is \n" << _fileContents_.str() << std::endl;
1 Like

Hi sjr,

thanks for the explanation and help. It works and I understand now the reason is due to missing string terminator at the array.