1

-fomit-frame-pointer と -mrtd を使用して GCC でコンパイルすると、この C コードはセグメンテーション違反でクラッシュします。

私のコードは何らかの形で間違っていますか? 他の関数ポインターは期待どおりに機能しますが、渡されている自由関数の場合はそうではありませんか? コンパイル時に警告が表示されますが、その理由や修正方法がわかりません。(私は通常、c でコーディングしません。このエラーは、私が使用する 3D パーツ ライブラリから発生します)

Windows で rtd/stdcall が必要であり、ctypes を使用して Python からこのライブラリを呼び出す必要があり、GCC で -O1 を使用してコンパイルすると、デフォルトで -fomit-frame-pointer が含まれます。(GCC のバージョンは TDM/Mingw32 の 4.6.1 です) デフォルトの最適化オプションが問題を引き起こすのは少し奇妙に感じますか?

Cコード:

#include <stdlib.h>

// void free ( void * ptr );
void test(void* o, void (*freeFunc)(void*)) {
    freeFunc(o);
}

int main() {
    int *p = (int *)calloc(1, sizeof(int));
    test(p, free);
}

以下でコンパイル:

gcc -fomit-frame-pointer -mrtd -c fx.c
gcc -fomit-frame-pointer -mrtd fx.o -o fx.exe

コンパイル警告:

fx.c: In function 'main':
fx.c:11:5: warning: passing argument 2 of 'test' from incompatible pointer type[enabled by default]
fx.c:5:6: note: expected 'void (*)(void *)' but argument is of type 'void (*)(void *)'
4

2 に答える 2

3

のGCCマニュアルページから-mrtd

Warning: this calling convention is incompatible with the one
normally used on Unix, so you cannot use it if you need to call
libraries compiled with the Unix compiler.

警告はちょっと奇妙ですが、互換性のない呼び出し規約を使用する関数へのポインターを渡していることを伝えようとしているだけだと思います。freein libc はそのような関数になると思います。通話がまったく機能することに驚いていcallocます。(あるいは、そうではないかもしれません。あなたが見ているのは遅延障害です!)

于 2012-06-05T18:01:19.333 に答える
1

少なくともこの単純な例では、cdecl 属性を使用して関数ポインターを適切に宣言することで、問題を解決できるはずです。これを試して:

#include <stdlib.h>

void test(void* o, void (__attribute__((cdecl))*freeFunc)(void*)) {
    freeFunc(o);
}

int main() {
    int *p = (int *)calloc(1, sizeof(int));
    test(p, free);
}
于 2012-06-05T21:16:55.290 に答える