【问题标题】:C MACRO to compare function names against predefined list of namesC MACRO 将函数名称与预定义的名称列表进行比较
【发布时间】:2020-01-16 12:25:02
【问题描述】:

我有一些功能要挂在 Windows 上(大约 200 个),我想为所有这些功能添加一些通用功能。根据我给我的应用程序的标志,挂钩或不挂钩一些预定义的功能。

我的想法是这样的:

#define SHOULD_CHECK_STOP_MONITOR           (1 == Configuration.dwShouldMonitor)
#define MY_CHECK_MACRO(f) (if(SHOULD_CHECK_STOP_MONITOR && /* What do I do here? */))

void MyHookedFunctionName_A(...)
{
    if(!MY_CHECK_MACRO(__FUNCTION__))
        goto lbl_Cleanup;

    /* rest of code logic */

lbl_Cleanup:
    return ...;
}

void MyHookedFunctionName_B(...)
{
    if(!MY_CHECK_MACRO(__FUNCTION__))
        goto lbl_Cleanup;

    /* rest of code logic */

lbl_Cleanup:
    return ...;
}

我想要实现的结果是一个预编译的逻辑,不是在动态运行时执行,而是在编译时执行。如果1 == Configuration.dwShouldMonitor 配置为True,它将检查其余逻辑,其中我将有某种预定义的函数名称列表["MyHookedFunctionName_A", "MyHookedFunctionName_C", "MyHookedFunctionName_D"],并且宏会知道是返回False 还是@ 987654326@ 基于函数名称。所以在这个例子中,MyHookedFunctionName_B 会执行,而MyHookedFunctionName_A 不会因为编译时的预定义列表。

这样的事情可能吗?对于基于函数名称的“复杂”逻辑并将其与预定义的字符串函数名称进行比较?

编辑 2019.09.15: 我在这里添加我希望预编译逻辑之后的结果

void MyHookedFunctionName_A(...)
{
    if(!(1 == Configuration.dwShouldMonitor && False))
        goto lbl_Cleanup;
...
}

void MyHookedFunctionName_B(...)
{
    if(!(1 == Configuration.dwShouldMonitor && True))
        goto lbl_Cleanup;
...
}

TrueFalse 是在编译时根据函数字符串名称生成的

【问题讨论】:

  • 我认为宏不可能。如果是 C++,你可以使用 constexpr 函数...
  • @HolyBlackCat ,C 中没有替代的等价物吗?我唯一的选择是在运行时的每个函数中执行这个逻辑?
  • 我想不出来,但我可能是错的。
  • 宏调用的结果是文本,通常是 C 或 C++ 程序的文本。完全不清楚您想要生成什么样的文本。您可以发布一些您希望在设置标志时生成的文本,以及一些您希望在未设置标志时从同一来源生成的文本吗?您不必在预处理之前发布源代码。正是您想在预处理后看到的。
  • 嘿@nm,我添加了我期望的结果,基于函数字符串名称,我希望它可以方便地创建TrueFalse 语句,我可以轻松控制所有我的功能,无需动态执行此逻辑

标签: c visual-studio macros precompile


【解决方案1】:

许多编译器应该能够完全优化您的“运行时”检查。

这里有一个简单的程序来说明这一点。

#include <string.h>
#include <stdio.h>

static const char* func_list[] = { "foo", "bar" };

static inline int is_in_list(const char* f) {
    for (int i = 0; i < sizeof(func_list)/sizeof(func_list[0]); ++i)
        if (strcmp(f, func_list[i]) == 0)
            return 1;
    return 0;
}

#define HOOKME if (SHOULD_HOOK && is_in_list(__func__)) return;

void foo() {
    HOOKME;
    printf("foo\n");
}
void bar() {
    HOOKME;
    printf("bar\n");
}
void baz() {
    HOOKME;
    printf("baz\n");
}

int main()
{
    foo();
    bar();
    baz();
}

用 -DSHOULD_HOOK=1 和 -O2 编译它,一个好的编译器可能会让 foobar 消失。

foo:
  ret
bar:
  ret
.LC0:
  .string "baz"
baz:
  mov edi, OFFSET FLAT:.LC0
  jmp puts
main:
  sub rsp, 8
  xor eax, eax
  call baz
  xor eax, eax
  add rsp, 8
  ret

并非所有编译器都能做到这一点。明智地选择你的工具。 Demo.

【讨论】:

  • 看起来像我正在寻找的东西,但无法真正让它工作,知道它是否应该与Microsoft Visual Studio 2015 编译器一起工作?
  • @0xAK 此特定代码不起作用(即 MSC 不会对其进行优化)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
  • 2021-10-16
相关资源
最近更新 更多