Search code examples
c++fstream

Why is fstream put function filling 4GB of space on my drive?


For whatever reason, my program is filling up 4GB of space on my drive. Why?

I narrowed it down to this for loop using breakpoints:

int blockPos = 1;
char blockAddressPos = 0x00;
for (int d = 0; d < img.width * img.height * img.channels; d++) {
    tf.write(blockPos, blockAddressPos, (char)img.data[d]);
    //printf("Byte write: %i\n", (unsigned int)img.data[d]);
    blockAddressPos++;
    break; // Debug purposes
    if (blockAddressPos >= 0xFF) {
        blockPos++;
        blockAddressPos = 0x00;
    }
}

The tf.write() function:

void TableFormatter::write(int block, char blockAddr, char data) {
    if (_valid) {
        if (block == 0) {
            if (blockAddr <= 0x0F) {
                // Core file metadata is located here, disallow write access or shift address to 0x10

                blockAddr = 0x10;
                _states.write.TableMetadataWarning = true;
            }
        }

        unsigned int location = (block << 8) | blockAddr;
        _table.seekp(location, FileBeginning);
        _table.put(data);
    } else {
        _states.fileSignatureInvalid = true;
    }
}

Anyone know why this is happening?


Solution

  • According to /J (Default char Type Is unsigned), by default char is signed in Visual C++. So after blockAddressPos exceeds 0x7F, it wraps around and most likely becomes negative, e.g. 0x80 = -128.

    When you pass this negative value to tf.write(), the line unsigned int location = (block << 8) | blockAddr; promotes blockAddr to int, which sign-extends. So you do the equivalent of location = (block << 8) | 0xFFFFFF80, which is where your ~4 GB comes from.

    You probably want to change blockAddressPos and the blockAddr parameter to be unsigned char, or better, uint8_t.

    (By the way, with that fixed, your test blockAddressPos >= 0xFF will write blocks of size 255 bytes, not 256; is that really what you want?)