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