What's the fastest way to check if a slice points to static data

via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Jun 24 05:22:54 PDT 2017


I need a fast and hopefully relatively cross-platform (ELF, OMF, 
COFF and MachO) way of checking if a slice points to data in the 
read-only section of the binary, i.e. it's pointing to a 
statically-allocated piece of memory.

<side_note>

Of course a simple solution using meta programming would be:

---
enum isStaticallyAllocated(alias var) = __traits(compiles,
{
     // ensures that the value is known at compile-time
     enum value = var;

     // ensures that it's not a manifest constant and that it's
     // actually going to be part of the binary (modulo linker
     // optimizations like gc-sections).
     static immutable addr = &var;
});

enum x = 3;
static immutable y = 4;
immutable z = 5;
int w = 6;

void main()
{
     enum localX = 3;
     static immutable localY = 4;
     immutable localZ = 5;
     int localW = 6;

     pragma (msg, isStaticallyAllocated!x); // false
     pragma (msg, isStaticallyAllocated!y); // true
     pragma (msg, isStaticallyAllocated!z); // true
     pragma (msg, isStaticallyAllocated!w); // false
     pragma (msg, isStaticallyAllocated!localX); // false
     pragma (msg, isStaticallyAllocated!localY); // true
     pragma (msg, isStaticallyAllocated!localZ); // false
     pragma (msg, isStaticallyAllocated!localW); // false
}
---

However, that doesn't work when all you have is a slice as a 
run-time
argument to a function.

</side_note>

Additionally, if the the slice was constructed from a string 
literal,
it should possible to recover a pointer to the zero-terminated 
string.

Or in pseudo-code:

---
void main()
{
     import core.stdc.stdio : printf;
     auto p = "test".fastStringZ;
     p || assert(0, "Something is terribly wrong!");
     printf("%s\n", p);
}

import std.traits : isSomeChar;

// Does the magic
bool isStaticallyAllocated(in scope void[] slice)
{
     // XXX_XXX Fix me!!!!
     return true;
}

/**
  * Returns:
  * A pointer to a null-terminated string in O(1) time,
  * (with regards to the length of the string and the required
  * memory, if any) or `null` if  * the time constraint
  * can't be met.
  */
immutable(T)* fastStringZ(T)(return immutable(T)[] s) @trusted
if (isSomeChar!T)
{
     if (isStaticallyAllocated(s) && s.ptr[s.length] == 0)
         return s.ptr;
     else
         return null;
}
---

(Without `isStaticallyAllocated`, `fastStringZ` may *appear* to
work but if you pass the pointer to e.g. a C library and that
library keeps it after the call has completed, good luck tracking
memory corruption if the slice was pointing to automatic/dynamic
memory - e.g. static array buffer on the stack or GC / RC * heap
allocation.
* malloc or custom allocator + smart pointer wrapper)


More information about the Digitalmars-d-learn mailing list