为什么std :: hex会导致内存损坏vector.size()?

时间:2019-02-20 14:32:39

标签: c++ iostream memory-corruption

我有以下代码:

vector<UINT_PTR> test = GetMemoryAddresses();

cout << "Size: " << test.size() << endl;

for (UINT_PTR a : test) {
    cout << "Memory Address: " << hex  << a << endl;
}

cout << "Size: " << test.size() << endl;

打印以下结果:

Size: 18
Memory Address: fc06a0
Memory Address: 13a70f0
Memory Address: 36c78c1
Memory Address: 3da0ea0
Memory Address: 3e21b80
Memory Address: c0a6881
Memory Address: c747690
Memory Address: c748b98
Memory Address: c74a1b8
Memory Address: c74ce10
Memory Address: c750c78
Memory Address: 1340a10f
Memory Address: 14376ea0
Memory Address: 14472649
Memory Address: 69867268
Memory Address: 6bdf9243
Memory Address: 7399a142
Memory Address: 76c54875
Size: 12

删除

  

<<十六进制

再次导致正确的vector.size()为18。

是什么原因导致此内存损坏?

我做错了什么吗?

有人可以启发我发生了什么事吗?

C ++总是让我惊讶的方式。

2 个答案:

答案 0 :(得分:9)

std::hex是“粘性”的。它将流的状态设置为十六进制显示,并且该状态将保持不变直到您对其进行更改。那意味着当你这样做

cout << "Size: " << test.size() << endl;

您以十六进制显示大小,十进制18表示12十六进制。

您需要

cout << "Size: " << dec << test.size() << endl;

切换回十进制模式并“正确”显示大小。


可以帮助您诊断的另一件事是使用std::showbase。它是另一个“粘性”操纵器,将在0x之前附加十六进制输出。在

中使用
cout << "Memory Address: " << hex << showbase  << a << endl;

将完成您的输出

Size: 18
Memory Address: 0xfc06a0
Memory Address: 0x13a70f0
Memory Address: 0x36c78c1
Memory Address: 0x3da0ea0
Memory Address: 0x3e21b80
Memory Address: 0xc0a6881
Memory Address: 0xc747690
Memory Address: 0xc748b98
Memory Address: 0xc74a1b8
Memory Address: 0xc74ce10
Memory Address: 0xc750c78
Memory Address: 0x1340a10f
Memory Address: 0x14376ea0
Memory Address: 0x14472649
Memory Address: 0x69867268
Memory Address: 0x6bdf9243
Memory Address: 0x7399a142
Memory Address: 0x76c54875
Size: 0x12

这使我们更加清楚,对cout的最后一次调用仍在使用hex

答案 1 :(得分:6)

std::cout << std::hex;

std::cout打印的所有数字打印为十六进制。要再次返回十进制,请运行:

std::cout << std::dec;

理想情况下,在使用任何流格式操纵器(如std::hex)之前,应保存格式标记并在完成后将其还原。例如:

auto flags = std::cout.flags();
std::cout << std::hex << 10 << "\n";
std::cout.flags( flags );

所有标志都需要像这样重置:https://en.cppreference.com/w/cpp/io/ios_base/flags

填充字符也很粘:https://en.cppreference.com/w/cpp/io/basic_ios/fill,精度也很粘:https://en.cppreference.com/w/cpp/io/ios_base/precision

唯一一个不是宽度标志:https://en.cppreference.com/w/cpp/io/ios_base/width

Boost具有一个实用程序类,用于将所有流状态重置为初始值:https://www.boost.org/doc/libs/1_69_0/libs/io/doc/ios_state.html