PyODBC Cursor.fetchall()导致python崩溃(segfault)

时间:2012-07-25 20:18:44

标签: python segmentation-fault pyodbc

我在Windows XP上使用Python 2.7。

我有一个简单的python脚本,它使用pyodbc从AR数据库中获取数据,该数据库一直运行到今天。一旦光标到达特定行,我就会得到一个段错误。我在C ++中有类似的代码,检索结果没有问题,所以我认为这是pyodbc的一个问题。无论哪种方式,我都想“抓住”这个错误。我试图使用子进程模块,但它似乎没有工作,因为一旦脚本遇到段错误它只是挂起“python.exe遇到问题,需要关闭。”信息。我想我可以设置一些任意的时间框架来完成它,如果没有,强制关闭过程,但这似乎有点蹩脚。

我也在这里报告了这个问题 - http://code.google.com/p/pyodbc/issues/detail?id=278

@ paulsm4 - 我在下面回答了你的问题,谢谢!

  问:你使用的是Windows / XP(我想象的是32位),Python 2.7和BMC   补救措施AR。正确的吗?

答:是的,它在Win XP 32位和Win Server 2008 R2 64位上失败。

  问:你有没有机会(或者你的客户,如果他们购买的话)   补救措施AR)可以与BMC打开支持电话吗?

答:可能不是......

  问:你能否确定哪一列导致了段错误? “什么是   不同的“当发生段错误时?

答:只是这一行...但我现在已将您的建议与以下问题隔离开来了。我使用循环来获取每个字段,直到出现段错误。

cursor.columns(table="mytable")
result = cursor.fetchall()
columns = [x[3] for x in result]
for x in columns:
    print x
    cursor.execute("""select "{0}"
                      from "mytable"
                      where id = 'abc123'""".format(x))
    cursor.fetchall()

一旦我确定了导致segfault的列,我就尝试了对所有列的查询,除了那个列,确定它没有问题。

列的数据类型为CHAR(1024)。我使用C ++来获取数据,并注意到该行的列中任何其他行中的字符数最多...... 1023!想想可能在PyODBC的C代码中有一个缓冲区,它正在被写入超出其边界的范围。

  

2)启用ODBC跟踪:http://support.microsoft.com/kb/274551

     

3)回发结果(包括失败的日志跟踪)

好的,我已经创建了一个带有ODBC跟踪结果的pastebin - http://pastebin.com/6gt95rB8。为了保护无辜,我掩盖了一些字符串值。

看起来可能是由于数据截断造成的。

这是否足以让我们了解如何解决问题?我认为这是PyODBC中的一个错误,因为直接使用C ODBC API可以正常工作。

更新

所以我编译PyODBC进行调试,我收到了一条有趣的消息 -

Run-Time Check Failure #2 - Stack around the variable 'tempBuffer' was corrupted.

虽然我目前不了解它,但调用堆栈如下 -

pyodbc.pyd!GetDataString(Cursor * cur=0x00e47100, int iCol=0)  Line 410 + 0xf bytes C++
pyodbc.pyd!GetData(Cursor * cur=0x00e47100, int iCol=0)  Line 697 + 0xd bytes   C++
pyodbc.pyd!Cursor_fetch(Cursor * cur=0x00e47100)  Line 1032 + 0xd bytes C++
pyodbc.pyd!Cursor_fetchlist(Cursor * cur=0x00e47100, int max=-1)  Line 1063 + 0x9 bytes C++
pyodbc.pyd!Cursor_fetchall(_object * self=0x00e47100, _object * args=0x00000000)  Line 1142 + 0xb bytes C++

解决!

通过确保缓冲区有足够的空间来解决问题。

第330行的getdata.cpp

char tempBuffer[1024];

更改为

char tempBuffer[1025];

编译并替换了site-packages中的旧pyodbc.pyd文件,我们都很好!

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

问:您使用的是Windows / XP(我想象的是32位),Python 2.7BMC Remedy AR。正确的吗?

问:你有没有机会(或者你的客户,如果他们购买了Remedy AR)可以打开与BMC的支持电话?

问:你能否确定哪一列导致了段错误?当发生段错误时“有什么不同”?

请执行以下操作:

1)使用Python / ODBC尝试不同的“选择a,b,c”语句,以查看是否可以重现问题(独立于您的程序)并隔离特定列(或理想情况下,特定列和行! )

2)启用ODBC跟踪: http://support.microsoft.com/kb/274551

3)回发结果(包括失败的日志跟踪)

4)如果这不起作用 - 如果你不能参与BMC技术支持 - 那么Plan B可能是在ODBC库级调试:

答案 1 :(得分:0)

对于其他可能会收到此错误的人,请检查返回的数据类型格式。就我而言,这是一个datetime列。使用select convert(varchar, getdate(), 20) from xxx或任何convert格式来获得所需的结果。