是什么让使用 ifstream 时检测到堆栈粉碎?

What makes stack smashing detected when use ifstream?

今天我在使用 clang++ifstream 时遇到异常错误:

*** stack smashing detected ***: <unknown> terminated

我的代码是这样的:

uint32_t Lod::getGraphicsOffset(std::ifstream *file, int graphicsNumber) {
    uint32_t filesAmount = 0;
    fileStream.seekg(76 + graphicsNumber*32);
    fileStream.read(reinterpret_cast<char*>(&filesAmount), 16);
    return filesAmount;
}

然而,当我只更改 fileAmount 代码中的位置时它是有效的:

uint32_t Lod::getGraphicsOffset(std::ifstream *file, int graphicsNumber) {
    fileStream.seekg(76 + graphicsNumber*32);
    uint32_t filesAmount = 0;
    fileStream.read(reinterpret_cast<char*>(&filesAmount), 16);
    return filesAmount;
}

有人知道为什么吗?是什么原因造成的?也许是一些UB?

在:

fileStream.read(reinterpret_cast<char*>(&filesAmount), 16);

将 16 个字节读入 4 个字节 filesAmount,这会破坏堆栈并导致未定义的行为。

修复:

fileStream.read(reinterpret_cast<char*>(&filesAmount), sizeof filesAmount);

您可能应该检查 read 的 return 值以确保它成功:

if(!fileStream.read(reinterpret_cast<char*>(&filesAmount), sizeof filesAmount))
    // Handle read failure.

这是未定义的行为。

fileStream.read(reinterpret_cast<char*>(&filesAmount), 16);

告诉fileStream将16个字节的数据放入filesAmountfilesAmount 然而是一个 uint32_t 意味着它只有 4 个字节大(假设一个 8 位字节)。因此,您开始在 filesAmount 结束后写入数据,这是不允许的。简单的解决方法是将其更改为

fileStream.read(reinterpret_cast<char*>(&filesAmount), sizeof(filesAmount));