使用-fomit-frame-pointer -mrtd编译c会在自由函数指针上创建段错误

时间:2012-06-05 17:53:54

标签: c gcc segmentation-fault

如果我使用-fomit-frame-pointer和-mrtd使用GCC进行编译,则此c代码会因分段错误而崩溃。

我的代码在某种程度上是错误的吗?其他函数指针按预期工作,但是当它的自由函数被传递时却没有?我在编译时收到警告,但我不明白为什么或应该做些什么来修复。 (我通常不用c编码,这个错误来自我使用的3d零件库)

我需要rtd / stdcall,因为我在Windows上需要使用ctypes从python调用此库,并且在使用-O1与GCC进行编译时默认包含-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 *)'

2 个答案:

答案 0 :(得分:3)

来自-mrtd的GCC手册页:

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.

警告有点奇怪,但我相信它只是试图告诉你,你正在向一个使用不兼容调用约定的函数传递指针。我想libc中的free就是这样一个函数;我很惊讶调用calloc可以工作。 (或许它不是,你所看到的是延迟失败!)

答案 1 :(得分:1)

至少在这个简单的例子中,您应该可以通过使用cdecl attribute正确声明函数指针来解决问题。试试这个:

#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);
}