我一直在将一个使用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指针的默认值是打印到stdout。现在有趣的是,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)
当我设置安静模式时,libsvm接受函数指针,但在调用svm_train
几秒后挂起,然后seg错误。我尝试创建一个void *
参数函数指针,然后将其转换为具有相同结果的const char *
函数指针,这意味着它不是从const char *
到PyStringObject的转换。
然后我终于编写了一个C ++函数,通过以下方式将函数指针设置为库中的no-op:
void print_null(const char *) {}
void svm_set_print_null() {
svm_set_print_string_function(&print_null);
}
按预期工作,没有分段错误。这让我认为ctypes在函数指针转换的某个内部点失败了。查看ctypes源文件并没有向我揭示任何明显的东西,虽然我没有明确地使用ctypes,所以很难缩小bug的位置。
我现在可以使用我的库添加解决方案,但是如果我想静默处理返回,我需要实际上能够将函数指针传递给libsvm。此外,如果我需要在不知道问题的真正根本原因的情况下实施此类变通办法,它不会让我对稳定性感到高枕无忧。
是否有其他人在Solaris上使用libsvm打印函数或在Solaris上使用Python中的ctypes函数指针时遇到问题?我找不到任何关于Solaris的问题的在线搜索。我打算使用库调用并使一些函数处理库来找到确切的失败边界,但是其他人的输入可能会让我节省一两天的调试测试。
更新
此问题在32位版本的Solaris 5.11上也是可重现的。