Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::hex lead to memory corruption vector.size()?

I have following code:

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;

Which prints following results:

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

Removing the

<< hex

leads to the correct vector.size() of 18 again.

What is causing this memory coruption?

Have I done anything wrong?

like image 991
Ojav Avatar asked Dec 04 '22 18:12

Ojav


2 Answers

std::hex is "sticky". It sets the state of the stream to hexadecimal display and that is where it will stay until you change it. That means when you do

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

you display the size in hex and 18 decimal is 12 hex.

You need

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

to switch back to decimal mode and display the size "correctly".


Another thing that would help you diagnosing this is to use std::showbase. It is another "sticky" manipulator and will prepend hexadecimal output with 0x. Using that in

cout << "Memory Address: " << hex << showbase  << a << endl;

would have made your output

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

which makes it a lot more clear that the last call to cout is still using hex

like image 95
NathanOliver Avatar answered Dec 11 '22 09:12

NathanOliver


std::cout << std::hex;

makes all numbers printed by std::cout print as hex. To get back to decimal again run:

std::cout << std::dec;

Ideally before using any stream format manipulators (like std::hex) you should save the formatting flags and restore them when you are finished. For example:

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

All of the flags need to be reset like this: https://en.cppreference.com/w/cpp/io/ios_base/flags

The fill character is also sticky: https://en.cppreference.com/w/cpp/io/basic_ios/fill and so is the precision: https://en.cppreference.com/w/cpp/io/ios_base/precision

The only one that isn't is the width flag: https://en.cppreference.com/w/cpp/io/ios_base/width

Boost has a utility class to reset all the stream state back to the initial values: https://www.boost.org/doc/libs/1_69_0/libs/io/doc/ios_state.html

like image 37
Alan Birtles Avatar answered Dec 11 '22 10:12

Alan Birtles