为什么 fstream put 函数占用了我的驱动器上的 4GB 空间?

all*_*e50 -1 c++ fstream

无论出于何种原因,我的程序占用了我的驱动器上 4GB 的空间。为什么?

我使用断点将其范围缩小到这个for循环:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

功能tf.write()

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么会发生这种情况?

Nat*_*dge 6

根据/J (Default char Type Is unsigned),在 Visual C++ 中默认char是有符号的。因此,在blockAddressPos超过后0x7F,它会回绕并且很可能变为负值,例如0x80 = -128

当您将此负值传递给 时tf.write(),该行将unsigned int location = (block << 8) | blockAddr;提升blockAddrint,并进行符号扩展。因此,您执行相当于 的操作location = (block << 8) | 0xFFFFFF80,这就是您的 ~4 GB 的来源。

您可能希望将blockAddressPos参数更改blockAddrunsigned char或更好uint8_t

(顺便说一句,修复后,您的测试blockAddressPos >= 0xFF将写入大小为 255 字节的块,而不是 256;这真的是您想要的吗?)