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)

Reply via email to