I am using c++ under 64 bit linux, the compiler (g++) is also 64 bit. When I print the address of some variable, for example an integer, it is supposed to print a 64 bit integer, but in fact it prints a 48 bit integer.
int i;
cout << &i << endl;
output: 0x7fff44a09a7c
I am wondering where are the other two bytes. Looking forward to you help.
Thanks.
The printing of addresses in most C++ implementations suppresses leading zeroes to make things more readable. Stuff like 0x00000000000013fd does not really add value.
When you wonder why you will normally not see anything more than 48bit values in userspace, this is because the current AMD64 architecture is just defined to have 48bit of virtual address space (as can be seen by e.g. cat /proc/cpuinfo on linux)
They are there - they haven't gone anywhere - it's just the formatting in the stream. It skips leading zeros (check out fill and width properties of stream).
EDIT: on second thoughts, I don't think there is a nice way of changing the formatting for the default operator<< for pointers. The fill and width attributes can be changed if you are streaming out using the std::hex manipulator.
For fun you could use the C output and see if it's more like what you're after:
printf("0x%p");
Related
I'm working with IEEE-754 doubles, and I'd like to verify that the bit patterns match between different platforms. For this reason I would like to see the bit pattern of a double in the Visual Studio C++ Debugger.
I've tried format specifiers, but they don't seem to allow me to format a double as anything which would allow me to see the bit pattern.
One way I finally found was to use Memory View and enter the address of the variable (&x) in the address field. This allows me to set for instance 8-bit integer hex display, which gives me what I need. But is there any other more convenient way of formatting a double this way in the debugger?
To view the exact binary floating-point value you should print the it as hexadecimal with %a/%A or std::hexfloat instead of examining its bit pattern
printf("Hexadecimal: %a %A\n", 1.5, 1.5);
std::out << std::hexfloat << 1.5 << '\n';
However if you really need to view the actual bit pattern then you just need to reinterpret the type of the underlying memory region like auto bits = reinterpret_cast<uint64_t*>(doubleValue). You don't need to open the Memory View to achieve this, a simple cast would work in the Watch window. So to get the bit pattern of double and float use *(__int64*)&doubleValue,x and *(int*)&floatValue,x respectively. Strict aliasing does occur but you don't actually need to care about it in MSVC debugger
Note that __int64 is a built-in type of MSVC so you might want to use long long instead. Typedefs and macros like uint64_t won't work while watching
Alternatively you can access the bytes separately by casting to char* and print as an array with (char*)&doubleValue, 8, (char*)&floatValue, 4 or (char*)&floatingPoint, [sizeof floatingPoint]. This time strict aliasing doesn't occur but the output may be less readable
I have a question about put or other derivatives of in fstream.h. Can I make sure about portability of the code when I want to simply write something like so:
#include <fstream>
#include <iostream>
using namespace std;
typedef unsigned char u8;
int main()
{
fstream f;
u8 ch;
f.open("deneme.txt",ios::out|ios::binary);
f.put(129);
f.close();
return 0;
}
When I write 128 into the put function (which takes type of char value as parameter) I took an € but for 129, it is nothing in the text file. I can't see, can't select. Although the cursor appear at the begining of the file, row,col pointer of the notepad interestingly say 1,2
So, there is something but it is not visible. Also according to tutorials, it was same as far as I remember. Can I write between 0 and 255 without portability issues. In order to ensure about that it writes correctly in binary form in all platforms (compilers/operating systems etc.). The cause of my concern is the char type whose range of value can change from platform to platform. Is there such a portability issue for put function or Do I have to worry about it in long run?
OK, I know what to do about that topic anymore. Thanks everybody trying to help me.
In fact, there are no issue at all. I don't know what OS do you use. But on *nix like OS it is very simple to check that you get what you want. Look at size of file I sure you it will be 1 byte. And if you open it in hex editor you get byte with value 0x81 or 129.
About editors, some modern editor may think that this 129 character is begin of UTF-8 sequence, and it has at least two bytes length and show wrong results. Another not modern editor may think that this is some 8bit local endcoding, but this encoding may not describe character 129, or font used by this editor may not contains such glyph. This is the problems of editors not your program.
I want to use a long integer that will be interpreted as a number when the MSB is set otherwise it will be interpreted as a pointer. So would this work or would I run into problems in either C or C++?
This is on a 64-bit system.
Edited for clarity and a better description.
On x86-64, you WILL have a pointer that is over 47 bits in address have the 63rd bit set, since all the bits above "max number of bits supported by the architecture" (which is currently 48) must all have the same value as the most significant bit of the value itself. (That is any address above 0007 FFFF FFFF FFFF will be FFF8 0000 0000 0000 - everything in between is "invalid" as a pointer)
That may well be addresses ONLY used by the kernel, but I'm not sure it's guaranteed to be.
However, I would try to avoid using tricks like this - it's likely to come back and haunt you at some point.
People have tried tricks like this before.
It never works out well in the long run.
Simply don't do it.
Edit: better link - see reference to 'bit31', which was previously never returned as set. Once it could be set (over 2 gigs of RAM, gasp!) it would break naughty programs and therefore programs needed to opt into this option once this much memory became the norm as people had used trickery like this (amongst other things). And now my lovely, short and to the point answer has become too long :-)
So would this work or would I run into problems in either C or C++?
Do you have 64 bits? Do you want your code to be portable to 32 bit systems? long does not necessarily have 64 bits. Big-endian v. little-endian? (Do you know which your system is?)
Plus, hopeless confusion. Please just use an extra variable to store this information or you will have many many bugs surrounding this.
It depends on the architecture. x86_64 architecture, for example, is currently using 48-bit addressing. It means that you could use 16 bits for your own needs (a trick that sometimes referred to as "pointer packing"). However, even the x86_64 architecture definition allows this limit to be raised in future implementations to the full 64 bits. If that happens, you may run into a situation where a lot of your code might need to be changed. So if you really must go that way, make sure your pointer packing is kept in one place that is easy to change in the future. For other architectures you have to check for yourself.
Unless you really need the space, or you're keeping alot of these things around, I would just use a plain union, and add a tag field. If you're going to go down that route, make sure that your memory is aligned to fit your needs.
Take a look at boost::lockfree::detail::tagged_ptr from boost.lockfree
This is a class that was introduced in latest 1_53 boost. It stores pointer and additional 16 bites in 64 bites variable.
Don't do such tricks. If you need to distinguish integers from pointers inside some container, consider using separate bit set to indicate such flag. In C++ std::bitset could be good enough.
Reasons:
Actually nobody guarantees pointers are long unsigned or long long unsigned. If you need
to store them, always apply sizeof() and void * type (if you need
to remove information about pointed object).
Even on one system addresses are highly dependent on architecture.
Kernel modules could seriously change mapping logics for process so you never know what addresses you will need.
Remember that the virtual address returned to your program does may necessarily line up to the actual physical address in memory. Infact, unless you are directly manipulating pretty special memory [e.g. some forms of graphics memory] then this is absolutely the case.
In this case, its the maximum value of the MMU which defines the values of the pointers your program sees. In which case, for x64 I'm pretty sure its (currently) 48bits, but as Mats specifies above once you've got the top bit set in the 48, you get the 63'd bit says aswell.
So taking his answer and mine - its entirely possible to get a pointer with the 47th bit set even with a small amount of RAM, and once you do you get the 63rd bit set.
If the "64-bit system" in question is x86_64, then yes, it will work.
I am using c++ under 64 bit linux, the compiler (g++) is also 64 bit. When I print the address of some variable, for example an integer, it is supposed to print a 64 bit integer, but in fact it prints a 48 bit integer.
int i;
cout << &i << endl;
output: 0x7fff44a09a7c
I am wondering where are the other two bytes. Looking forward to you help.
Thanks.
The printing of addresses in most C++ implementations suppresses leading zeroes to make things more readable. Stuff like 0x00000000000013fd does not really add value.
When you wonder why you will normally not see anything more than 48bit values in userspace, this is because the current AMD64 architecture is just defined to have 48bit of virtual address space (as can be seen by e.g. cat /proc/cpuinfo on linux)
They are there - they haven't gone anywhere - it's just the formatting in the stream. It skips leading zeros (check out fill and width properties of stream).
EDIT: on second thoughts, I don't think there is a nice way of changing the formatting for the default operator<< for pointers. The fill and width attributes can be changed if you are streaming out using the std::hex manipulator.
For fun you could use the C output and see if it's more like what you're after:
printf("0x%p");
While debugging a Linux app, I found a pointer with the suspicious value 0x7c7c7c7c. Does that particular value indicate anything?
(I ask because I know from my MSVC days that in a debug build, values like 0xcdcdcdcd or 0xdddddddd would be stored into heap blocks that were uninitialized, freed, or otherwise invalid. Some people use magic values like 0xdeadbeef or 0xcafebabe in uninitialized memory. I'm guessing something in libc or elsewhere uses 0x7c7c7c7c as a magic value, but I can't find it documented.)
I don't recognize that magic number, and neither does Wikipedia. I would guess that some code in your program (or in a library you're using) is using memset() and hitting your pointer. Have you grepped your code base case-insensitively for the string "0x7c"?
0x7C is an ASCII pipe "|" character. You could search for writes of that character as well 124 and 0x7C as Adam suggested.
0x7c7c = 01111100 01111100 in binary. That could be one of those "most difficult to read" bit patterns that format utilities fill unused space on hard drives with.
Maybe the MALLOC_PERTURB_ environment variable is set? If set, it influences how malloc() initializes the allocated memory.