2

私の問題は次のとおりです。

次のような関数ポインタを含む構造があります。

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

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

今、まさにそのタイプの関数ポインタをそれに割り当てたいと思います。しかし悲しいことに、次のようなものではなくa をdlsym()返していますvoid *function_poitner_type

だから私の最初の試み:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

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

警告で終了しました:

警告: ISO C では、関数ポインタと 'void *' の間の割り当てが禁止されています

わかりました、それは私を混乱させました... gccは私にそれほど厳しいことを話したことはありませんでした。しかし、ちょっとトリッキーにしましょう。標準準拠を維持するためのバックドアがおそらくあると思いました。だから私はこれを試しました:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

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

うーん……たしかに……

警告: 型打ちされたポインターを逆参照すると、厳密なエイリアシング規則が破られます

内部で何が起こっているのかわからないので、関数をエイリアスする実数が返されるか、まったく別の何かdlsym()が返されるため、壊れるかどうかわかりません。void *

したがって、この関数ポインターを使用すると、厳密なエイリアスルールが破られるのか、それとも破れないのかわかりません。

とにかく、私の会社では、 compilerflag を使用することは法律-fstrict-aliasingです。したがって、これは、適合したとしても、私にとって可能な解決策ではありません。

というわけで続けてみました。

私の次のアイデアは、 のchar *バージョンdlsym()を memcopy に解析するにはどうすればよいかということでした。

結果:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

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

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

私が今得ている警告は、かなり具体的です:

警告: ISO C は、関数ポインタと void * の間で 'memcpy' の引数 1 を渡すことを禁止しています

だから私の次のアイデアは、「バイトに戻ろう」というものでした。(しかし、徐々にアイデアが不足しています...)

だから私はした:

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];
    }

}

これは静かな別の警告で終わりました:

警告: ISO C では、関数ポインタからオブジェクト ポインタ型への変換が禁止されています

最後に、私の最も奇妙な試みは次のとおりです。

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];
    }
}

そしてここでも問題は、それが関数ポインターであるため、offsetoff2番目のパラメーターに変換できないことです。void *

私は立ち往生していて、さらに先に進む方法がわかりません。誰かが解決策を見つけるのを手伝ってくれますか?

clangではなくgcc 4.2を使用すると、これらの警告が表示されます。

対象となる C バージョンは、-std=c99回避することです。-std=POSIX-std=gnu99

しかし、この gcc 警告は私には時代遅れに聞こえません。私は現在 FreeBSD に取り組んでいますが、これを解決する方法がまったくわかりません。

4

2 に答える 2

2

これはちょっとトリッキーです:

#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()ます。

于 2013-10-01T13:10:00.953 に答える
0

2 つの型キャストを使用します。

func_type *funptr;
funptr= (func_type *)(intptr_t)dlsym();

コード ポインタとデータ ポインタのサイズが等しくない場合、型キャスト funptr は問題を引き起こします。

于 2016-08-28T16:49:58.237 に答える