c - 如何将 dlsym() 的返回值分配给函数类型?

标签 c gcc function-pointers freebsd strict-aliasing

我的问题如下:

我有一个包含函数指针的结构,如下所示:

typedef void (CALLING_COVNENTION * functionType_t) (/*...*/);

typedef struct myFuncpointerStruc_s
{
    /*...*/
    functionType_t funcIdentifier;
    /*...*/
}myFuncpointerStruc_t;

现在我想为其分配一个完全相同类型的函数指针。 但遗憾的是 dlsym() 返回的是 void * 而不是 function_poitner_type

所以我的第一次尝试:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

    structIdentifier.funcIdentifier= dlsym (hAndle, "calledName");
}

以警告结束:

WARNING: ISO C forbids assignment between function pointer and 'void *'

好吧,这让我很困惑……海湾合作委员会从来没有对我说过那么严厉的话。 但好吧,让我们变得棘手,我认为可能会有任何后门来保持其标准一致。所以我尝试了这个:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

    *(void **) &structIdentifier.funcIdentifier = dlsym (hAndle, "calledName");
}

嗯......显然......

warning: dereferencing type-punned pointer will break strict aliasing rules

因为我不知道dlsym()内部发生了什么,所以我不知道我会中断,因为我返回了一个真正的void *,它为我的函数起别名,或者完全不同的东西,可以吗?

所以我不知道,现在使用这个函数指针是否会违反严格别名规则?

但无论如何:对于我的公司来说,使用编译器标志 -fstrict-aliasing 是合法的。 所以这对我来说也不是一个可能的解决方案,即使它是符合要求的。

所以我继续尝试。

我的下一个想法是:如何将 dlsym()char * 版本解析为 memcopy?

结果:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

    unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");  

    memcpy (g_interfaceSvCheck.pfnPFD_SVCHK_GET_VERSION, localTestPtr, sizeof (localTestPtr));
}

我现在收到的警告再次非常具体:

warning: ISO C forbids passing argument 1 of ´memcpy´ between function pointer and ´void *´

所以我的下一个想法是“让我们回到字节”也许我会找到一种可行的方法。 (但慢慢地我就没有想法了......)

所以我做到了:

functionscope ()
{
    size_t testIndex;
    myFuncpointerStruc_t structIdentifier;
    unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");

    for (testIndex = 0; testIndex < sizeof (localTestPtr); testIndex++)
    {
        ((unsigned char *)(structIdentifier.funcIdentifier))[testIndex] = ((unsigned char *)&localTestPtr)[testIndex];
    }

}

这以一个安静的不同警告结束:

WARNING: ISO C forbids conversion of function pointer to object pointer type

所以最后我最奇怪的尝试是:

functionscope ()
{
    size_t testIndex;
    myFuncpointerStruc_t structIdentifier;
    unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");  
    unsigned char * FakeFunctionPointer;

    FakeFunctionPointer = 
        (((unsigned char *)structIdentifier) + offsetof (myFuncpointerStruc_t , funcIdentifier));

    for (testIndex = 0; testIndex < sizeof (localTestPtr); testIndex++)
    {
        FakeFunctionPointer[testIndex] = ((unsigned char *)&localTestPtr)[testIndex];
    }
}

即使在这里,问题是,offsetoff 的第二个参数无法转换为 void *,因为它是一个函数指针。

我陷入困境,不知道如何进一步发展,有人可以帮我找到解决方案吗?

我只是使用 gcc 4.2 而不是 clang 收到这些警告。

objective-c 版本是 -std=c99,要避免的是 -std=POSIX-std=gnu99

但是这个 gcc 警告对我来说听起来并没有过时。 我目前正在 FreeBSD 上工作,我真的不知道如何解决这个问题。

最佳答案

这有点棘手:

#define CALLING_CONVENTION 

typedef void (CALLING_CONVENTION * functionType_t) (/*...*/);
typedef struct myFuncpointerStruc_s
{
  /*...*/
  functionType_t funcIdentifier;
  /*...*/
} myFuncpointerStruc_t;

int main()
{
  myFuncpointerStruc_t structIdentifier = {0};

  {
    functionType_t * pfuncIdentifier = &structIdentifier.funcIdentifier;

    *(void **) (pfuncIdentifier) = dlsym(handle, "calledName");
  }

  ...
}

上面的解决方案只是欺骗编译器。 不再-O1上工作......:-(


确实没有办法解决,唯一的办法就是让编译器冷静下来。 GNU 人们对此表现出了洞察力并发明了:__attribute__ ((__may_alias__))

这里我们可以按如下方式使用它:

#define CALLING_CONVENTION 

typedef void * __attribute__ ((__may_alias__)) pvoid_may_alias_t;

typedef void (CALLING_CONVENTION * functionType_t) (/*...*/);
typedef struct myFuncpointerStruc_s
{
  /*...*/
  functionType_t funcIdentifier;
  /*...*/
} myFuncpointerStruc_t;

int main()
{
  myFuncpointerStruc_t structIdentifier = {0};

  *(pvoid_may_alias_t *) (&structIdentifier.funcIdentifier) = dlsym(handle, "calledName");
  }

  ...
}

顺便说一句:ldsym() 从哪里来?我只知道dlsym()

关于c - 如何将 dlsym() 的返回值分配给函数类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19116487/

相关文章:

c++ - OSX GCC 如何指定 sfml 库源?

c++ - Multimap 和 shared_ptr

c - 指针作为函数返回和 malloc 的使用

c++ - C++中的函数指针歧义

c - 启动失败。在 Eclipse 中找不到二进制文件

c - 单元测试kill命令

c - 如何正确清除结构数组

C++ 打印函数的结果?

c++ - 循环内是否有常量函数返回值的优化?

c++ - 如何强制Bazel使用gcc?