-1

I use Windows 10 OS Pc and build in environment debug x64 mode. I used Visual Studio 2019.

example code

int * d = new int;

-Memory-

&d is  30 45 0f 2f 12 02 00 00

Actually, in this case, it seems that the upper 2 bytes are not used.

Is there a case to use up to this part?.

I'm trying to put a memory usage count in this empty space(2byte).

bolov
  • 72,283
  • 15
  • 145
  • 224
2bbear
  • 1
  • 4
  • 4
    `&d` is the address of your pointer, not the thing it points *to*. – Botje Nov 24 '20 at 10:57
  • could you please elaborate, what you are trying to achieve? – TruthSeeker Nov 24 '20 at 10:57
  • 2
    The technique you're looking for is called pointer tagging. On x86_64, you can store some data in the [lower 3 bits of a pointer](https://en.wikipedia.org/wiki/Tagged_pointer) and in [bits 48 through 63](https://en.wikipedia.org/wiki/X86-64#Canonical_form_addresses) – Botje Nov 24 '20 at 11:00
  • 1
    Don't. First of all this is virtual address in process memory space, which means, that OS is free to gets you any value it wants. Second, it's managed by OS, and Windows used to actually use the oldest bit back in times when x86 was a brand new thing, so consider it reserved. And finally, why? Why do you want to use 2 bytes to store, what I assume is supposed to be reference counter, while there is dedicated template for that called shared_ptr? Besides, you have to realize there will be real performance penalty and you would have to manually manipulate the address each time you want to use it. – NRUB Nov 24 '20 at 11:01

3 Answers3

2

In C++ 64-bit environment, is there a case where the result Pointer of the new operator uses all 8 bytes?

There is no general guarantee applying to all 64 bit CPU architectures, that some of the bytes of a pointer would be unused.

In latest implementations of the x86-64 architecture, the high 16 bits of a virtual address are required to be copies of the highest preceding bit, leaving only 48 bits for the address space. The specification allows this to be extended up to the full 64 bits in future (256 TB ought to be enough for anybody though... right?).

The ability to take advantage of the "unused" bytes of the CPU architercture depends on whether the language implementation (operating system, compiler, sanitisers, ...) uses them already.

I'm trying to put a memory usage count in this empty space(2byte).

Using the high bytes of a pointer may be possible as long as you are aware that it will restrict the portability of your program to other operating systems and CPUs. Consider if you care whether your program still works in 10 years.

You must however be careful to restore the high bits before indirecting through the pointer on x86-64 even though they are "unused" (see the reason above).

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

In C++ 64-bit environment, is there a case where the result Pointer of the new operator uses all 8 bytes?

Apparently not on 64-bit Windows (yet!):

Virtual address spaces

The range of virtual addresses that is available to a process is called the virtual address space for the process. Each user-mode process has its own private virtual address space. For a 32-bit process, the virtual address space is usually the 2-gigabyte range 0x00000000 through 0x7FFFFFFF. For a 64-bit process on 64-bit Windows, virtual address space is the 128-terabyte range 0x000'00000000 through 0x7FFF'FFFFFFFF.

It appears the entire upper 2 bytes are unused on 64-bit Windows as of 02/11/2020 - the date specified in the link.

Of course, any update to a system does risk changing that...

Linux does use the entire virtual address space range, however.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
-1

In C++ 64-bit environment, is there a case where the result Pointer of the new operator uses all 8 bytes?

As others explained, not in 2020 (in practice). However, be aware of a few potential issues.

  • such tagged pointers would probably make your executable slower (in some cases - please benchmark), since every time you want to dereference your tagged pointer, you'll need to do something before on it.

  • your code is likely to become much less readable and harder to maintain by future contributors to it

  • your code might disable interesting compiler optimizations

  • your code is likely to be much less portable to other operating systems (including future releases of Windows or Linux) and other architectures (e.g. ARM or PowerPC)

  • your code probably won't win much memory space. The pointed data (in C++, its sizeof) is likely to have more than one word, in particular when it contains several standard C++ containers ore more than one pointer, so you would win maybe 10% of RAM only (and performance would be slower) since most of your C++ aggregate types (class-es, struct-s) have more than one word (as soon as you use virtual, there is likely to be a hidden virtual method table pointer).

  • you would spend a lot more debugging efforts.

I'm trying to put a memory usage count in this empty space (2 bytes).

  • you could encounter situations where the reference counter would overflow the 16 bits you use for it. So you might need to check for that case, and such runtime checks would make your executable even slower.

So at your place, I would discuss such an approach with your client or manager, and I don't recommend it.

It seems that you want to implement some kind of crude garbage collection. Be sure to read the GC handbook, since there are other approaches (in particular, Cheney's algorithm). Read at least more about tracing garbage collection, and take inspiration from existing open source implementations (e.g. SBCL or Ocaml).

Consider reading conference papers related to garbage collection and programming language implementation issues - e.g. ACM SIGPLAN conferences (in particular PLDI).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • `such tagged pointers would probably make your executable slower ... and performance would be slower` That's kind of an overly broad statement. Tagged pointers are used quite a *bit* and most often because they can make the program faster. Sure it is a trade-off and as such it *can* be slower too in some cases and it should be measured to compare with the trivial alternative. But that applies to pretty much every optimisation ever. – eerorika Nov 24 '20 at 12:07
  • Modern CPUs are memory bottlenecked, so extra few instructions may be unnoticeable because the core stalls on cache misses anyway. – Maxim Egorushkin Nov 24 '20 at 12:17
  • Yes, but this becomes even specific to a given chip. – Basile Starynkevitch Nov 24 '20 at 12:19
  • `so you would win maybe 10% of RAM only` Consider `struct {int* ptr; };` vs `struct {int* ptr; short size; };` The size increase is 100% on most systems. That's twice as many objects to fit in cache (P.S. not my downvote) – eerorika Nov 24 '20 at 12:19
  • But most `struct` have more than two words... (e.g. look inside source code of [Qt](https://qt.io/)...) – Basile Starynkevitch Nov 24 '20 at 12:20