我一直在将一个使用 libsvm 的 Python 包移植到一些生产服务器上,并遇到了一个奇怪的分段错误,我追踪到了一个 ctypes 函数指针。我正在尝试确定 ctypes 包装器失败的位置以及这是否是特定于发行版的问题。
我运行它的系统是一个非常干净的虚拟机,几乎没有安装任何东西:Solaris 5.11 amd64 pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86 Python 2.7.2
现在是问题描述以及我如何缩小到 ctypes。在 libsvm 中,您可以通过将void (*print_func)(const char *)
指针传递给函数来指定打印svm_set_print_string_function
函数。NULL 指针的默认设置是打印到标准输出。现在有趣的部分是 libsvm 的 Python 包装器(在各种其他系统上都可以正常工作)在通过以下方式请求安静模式(不打印)时会生成这样一个函数指针:
PRINT_STRING_FUN = CFUNCTYPE(None, c_char_p)
def print_null(s):
return
if argv[i] == "-q":
self.print_func = PRINT_STRING_FUN(print_null)
libsvm.svm_set_print_string_function(self.print_func)
svm_train
当我设置安静模式时,libsvm 接受函数指针,但在调用然后 seg 错误时会在几秒钟后挂起。我尝试制作一个void *
参数函数指针,然后将其转换为const char *
具有相同结果的函数指针,这意味着它不是从const char *
PyStringObject 的转换。
然后我终于写了一个 C++ 函数,通过以下方式将函数指针设置为库本身中的空操作:
void print_null(const char *) {}
void svm_set_print_null() {
svm_set_print_string_function(&print_null);
}
它按预期工作,没有分段错误。这让我认为 ctypes 在函数指针转换的某个内部点失败了。尽管我没有明确地使用 ctypes 进行大量工作,但查看 ctypes 源文件并没有发现任何明显的东西,因此很难缩小可能存在的错误。
我现在可以使用我的库添加解决方案,但如果我想静默处理返回,我实际上需要能够将函数指针传递给 libsvm。另外,如果我需要在不知道问题的真正根本原因是什么的情况下实施此类变通办法,它不会让我对稳定性高枕无忧。
有没有其他人对 Solaris 上的 libsvm 打印函数或 Solaris 上的 Python 中的 ctypes 函数指针有问题?我在网上找不到任何关于 Solaris 的此类问题的搜索。我计划玩弄库调用并制作一些函数处理库以找到故障的确切边界,但其他人的输入可能会为我节省一两天的调试测试。
更新
该问题在 Solaris 5.11 的 32 位版本上也可以重现。