69 Stimmen

Hat schon einmal jemand das Präprozessormakro __COUNTER__ verwendet?

El __COUNTER__ Symbol wird bereitgestellt von VC++ und GCC und ergibt bei jeder Verwendung einen zunehmenden nicht-negativen Integralwert.

Ich bin daran interessiert, zu erfahren, ob jemand es jemals benutzt hat, und ob es etwas ist, das es wert wäre, standardisiert zu werden?

0voto

Devolus Punkte 20928

In unserem Code haben wir vergessen, Testfälle für einige unserer Produkte hinzuzufügen. Ich habe jetzt einige Makros implementiert, damit wir zur Kompilierzeit sicherstellen können, dass wir für jedes Produkt, das wir hinzufügen oder entfernen, Testfälle haben.

0voto

SSpoke Punkte 5453

__COUNTER__ ist sehr nützlich, wenn Sie Zeichenketten zur Laufzeit verschlüsseln und Sie wollen, dass jede Zeichenkette einen eindeutigen Schlüssel hat. Ohne irgendwo einen Zähler für den Schlüssel Ihrer Verschlüsselung zu speichern, können Sie Counter verwenden, um sicher zu sein, dass jede Zeichenkette ihren eigenen eindeutigen Schlüssel hat!

Ich verwende es in meinem XorString 1 Header-Bibliothek, die Zeichenketten während der Laufzeit entschlüsselt, so dass Hacker/Cracker, die versuchen, meine Binärdatei einzusehen, die Zeichenketten dort nicht finden, aber wenn das Programm läuft, wird jede Zeichenkette entschlüsselt und normal angezeigt.

#pragma once
#include <string>
#include <array>
#include <cstdarg>

#define BEGIN_NAMESPACE( x ) namespace x {
#define END_NAMESPACE }

BEGIN_NAMESPACE(XorCompileTime)

constexpr auto time = __TIME__;
constexpr auto seed = static_cast< int >(time[7]) + static_cast< int >(time[6]) * 10 + static_cast< int >(time[4]) * 60 + static_cast< int >(time[3]) * 600 + static_cast< int >(time[1]) * 3600 + static_cast< int >(time[0]) * 36000;

// 1988, Stephen Park and Keith Miller
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
// with 32-bit math and without division

template < int N >
struct RandomGenerator
{
private:
    static constexpr unsigned a = 16807; // 7^5
    static constexpr unsigned m = 2147483647; // 2^31 - 1

    static constexpr unsigned s = RandomGenerator< N - 1 >::value;
    static constexpr unsigned lo = a * (s & 0xFFFF); // Multiply lower 16 bits by 16807
    static constexpr unsigned hi = a * (s >> 16); // Multiply higher 16 bits by 16807
    static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // Combine lower 15 bits of hi with lo's upper bits
    static constexpr unsigned hi2 = hi >> 15; // Discard lower 15 bits of hi
    static constexpr unsigned lo3 = lo2 + hi;

public:
    static constexpr unsigned max = m;
    static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
};

template <>
struct RandomGenerator< 0 >
{
    static constexpr unsigned value = seed;
};

template < int N, int M >
struct RandomInt
{
    static constexpr auto value = RandomGenerator< N + 1 >::value % M;
};

template < int N >
struct RandomChar
{
    static const char value = static_cast< char >(1 + RandomInt< N, 0x7F - 1 >::value);
};

template < size_t N, int K, typename Char >
struct XorString
{
private:
    const char _key;
    std::array< Char, N + 1 > _encrypted;

    constexpr Char enc(Char c) const
    {
        return c ^ _key;
    }

    Char dec(Char c) const
    {
        return c ^ _key;
    }

public:
    template < size_t... Is >
    constexpr __forceinline XorString(const Char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... }
    {
    }

    __forceinline decltype(auto) decrypt(void)
    {
        for (size_t i = 0; i < N; ++i) {
            _encrypted[i] = dec(_encrypted[i]);
        }
        _encrypted[N] = '\0';
        return _encrypted.data();
    }
};

//--------------------------------------------------------------------------------
//-- Note: XorStr will __NOT__ work directly with functions like printf.
//         To work with them you need a wrapper function that takes a const char*
//         as parameter and passes it to printf and alike.
//
//         The Microsoft Compiler/Linker is not working correctly with variadic 
//         templates!
//  
//         Use the functions below or use std::cout (and similar)!
//--------------------------------------------------------------------------------

static auto w_printf = [](const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf_s(fmt, args);
    va_end(args);
};

static auto w_printf_s = [](const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf_s(fmt, args);
    va_end(args);
};

static auto w_sprintf = [](char* buf, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vsprintf(buf, fmt, args);
    va_end(args);
};

static auto w_sprintf_ret = [](char* buf, const char* fmt, ...) {
    int ret;
    va_list args;
    va_start(args, fmt);
    ret = vsprintf(buf, fmt, args);
    va_end(args);
    return ret;
};

static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vsprintf_s(buf, buf_size, fmt, args);
    va_end(args);
};

static auto w_sprintf_s_ret = [](char* buf, size_t buf_size, const char* fmt, ...) {
    int ret;
    va_list args;
    va_start(args, fmt);
    ret = vsprintf_s(buf, buf_size, fmt, args);
    va_end(args);
    return ret;
};

//Old functions before I found out about wrapper functions.
//#define XorStr( s ) ( XorCompileTime::XorString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char >( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ).decrypt() )
//#define XorStrW( s ) ( XorCompileTime::XorString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t >( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ).decrypt() )

//Wrapper functions to work in all functions below
#define XorStr( s ) []{ constexpr XorCompileTime::XorString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char > expr( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ); return expr; }().decrypt()
#define XorStrW( s ) []{ constexpr XorCompileTime::XorString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t > expr( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ); return expr; }().decrypt()

END_NAMESPACE

-2voto

thegreendroid Punkte 3091

Ich beabsichtige, die __COUNTER__ um jeder Datei in unserer Codebasis einen eindeutigen Bezeichner zu geben, so dass dieser eindeutige Code bei der Protokollierung von ASSERTs in einem eingebetteten System verwendet werden kann.

Diese Methode ist viel effizienter als die Verwendung von Strings zum Speichern von Dateinamen (mit __FILE__ ), insbesondere bei einem eingebetteten System mit winzigem ROM. Ich dachte über diese Idee nach, als ich diesen Artikel las. Setzen Sie sich durch auf Embedded.com. Es ist eine Schande, dass es nur mit GCC-basierten Compilern obwohl funktioniert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X