HCSF
HCSF

Reputation: 2649

Gather Addresses of all Static C Strings at Compile Time

Let's say I have a function like

void foo(const char* bar, ...)

And it has been called in multiple places.

Is it possible to gather addresses of all static strings that are known at compile time in main()?

For example, foo("abc"), I want in main() to be able to get the address of "abc". If someone calls foo(someVariable), the address of someVariable might not be known, and so it can be ignored.

Is it possible?

Upvotes: 3

Views: 614

Answers (2)

Jarod42
Jarod42

Reputation: 217283

If you agree to use registration, you might do something like

// Would contain each registered string.
std::vector<const char*>& registered_vector()
{
    static std::vector<const char*> v;
    return v;
}

bool Register(const char* s)
{
    registered_vector().push_back(s);
    return true;
}

// Class which holds the unique pointer as buffer.
template <typename Char, Char... Cs>
struct static_string
{
    static constexpr Char s[] = {Cs..., 0};
};

template <typename Char, Char... Cs>
constexpr Char static_string<Char, Cs...>::s[];

// string literal operator templates are a GNU extension
// MACRO can replace the operator to avoid that extension.
template <typename Char, Char... Cs>
static_string<Char, Cs...> operator ""_ss()
{
    static_string<Char, Cs...> res;
    static const bool dummy = Register(res.s); // Register only once :-)
    static_cast<void>(dummy); // Avoid warning for unused variable
    return res;
}

And now, test it:

int main() {
    "Hello"_ss;
    "World"_ss;
    "Hello"_ss;
    "Hi"_ss;
    "42"_ss;

    for (const auto s : registered_vector()) {
        std::cout << s << std::endl;
    }
}

Demo

Upvotes: 2

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136266

Is it possible to gather addresses of all static strings that are known at compile time in main()?

At compile time strings from other translation units are unavailable.

You can dump string literals from your executable or shared library using readelf -W -p .rodata <executable> command.

Upvotes: 1

Related Questions