我一直在从事一个在专用 Linux CentOS 系统上运行良好的项目。
一般的想法是有一个 Python 工作流管理器,而不是使用 ctypes 调用用 C 编写的共享库。它工作正常。
但是,出于开发目的,我需要有一个项目的本地实例。我在 Windows 7 下使用 VMWare 设置了 Linux Mint 虚拟机。在大多数情况下,一切正常。
问题是一个模块在调用其中一个共享库中的函数时因分段错误而崩溃。通常这没问题,在专用的 Linux 机器上,使用“gdb python corename”之类的东西可以让我准确地看到它崩溃的位置并解决问题。
但是,使用本地设置时我遇到了问题。我最注意到的是 GDB 没有报告正确的内存地址。这是一个巨大的项目,所以我不能发布所有代码,但我会给出一个纲要:
Python 模块创建一个“file_path”变量,一个字符串。它首先将其传递给某个共享库以加载文件。如果我执行命令,在 python
hex(id(file_path))
它会返回类似'46cb4ec'的东西。在第一个共享库中,即 C,我开始使用
printf("file_pathaddress = %x\n", &file_path[0]);
它输出'file_path address = 46cb4ec',这与我通过Python的'id()'函数得到的结果相同。我想这是预期的......?
无论如何..我将这个相同的变量发送到另一个共享库,但它在此调用时立即崩溃。如果我分析核心文件,它会显示它在函数调用本身上崩溃,而不是函数内的一行。但是,奇怪的是它输出如下内容:
Program terminated with signal 11, Segmentation fault.
#0 0x00007f124448c9fc in seam_processor (irm_filename=<error reading variable: Cannot access memory at address 0x7fff5fab51b8>,
seam_data_path=<error reading variable: Cannot access memory at address 0x7fff5fab51b0>,
full_data_path=<error reading variable: Cannot access memory at address 0x7fff5fab51a8>, ranges=<error reading variable: Cannot access memory at address 0x7fff5fab51a0>,
job_id=<error reading variable: Cannot access memory at address 0x7fff5fab519c>, job_owner=<error reading variable: Cannot access memory at address 0x7fff5fab5198>,
y_tile_in=1, x_tile_in=1, fc_int=10650000000, atmos_props=..., surf_props=..., extra_props=<error reading variable: Cannot access memory at address 0x7fff5fab5190>,
gascalc_ftype=513, len_gas_sectrum=16, vect_spec_fq=<error reading variable: Cannot access memory at address 0x7fff5fab5188>, surfscat_theta_inc_vector_size=6,
surfscat_theta_inc_vector=<error reading variable: Cannot access memory at address 0x7fff5fab5180>, surfscat_phi_inc_vector_size=6,
surfscat_phi_inc_vector=<error reading variable: Cannot access memory at address 0x7fff5fab5178>, surfscat_theta_scat_vector_size=6,
surfscat_theta_scat_vector=<error reading variable: Cannot access memory at address 0x7fff5fab5170>, surfscat_phi_scat_vector_size=6,
surfscat_phi_scat_vector=<error reading variable: Cannot access memory at address 0x7fff5fab5168>) at src/seam_processor.c:47
所以,我不明白为什么 GDB 会报告这些内存地址。在这种情况下,'irm_filename' 变量是 Python 作为 'file_path' 传入的,因此它的地址应该是其他库和 id() 函数报告的内容,0x46CB4EC。为什么不一样?然而,奇怪的是,有些变量很好,比如'y_tile_in'。如果我在 gdb 中这样做:
(gdb) print &y_tile_in
$1 = (int *) 0x7fff60543f80
因此,尽管它可以读取此内存地址,但这与 Python 的 id() 将报告的内容不同,或者该地址的类似 C printf() 将在不会崩溃的库中报告的内容不同。此外,这些内存地址是非常大的数字,比我目前拥有的内存量还要大......它们的真正含义是什么?
那么,我的问题是,这里到底发生了什么?这是在虚拟机中运行的事实吗?有一些映射正在进行吗?如果在虚拟机中使用 gdb,我无法在网上找到任何关于我必须做的不同的事情,所以我很茫然......
有谁知道发生了什么?
谢谢。
编辑
所以,这个问题变得陌生了。基本上,我注释掉了库中所有可以做任何事情的代码,并让函数调用保持不变。当我这样做并在带有断点的 gdb 中运行它时,它在函数调用中打印的所有内存地址都是正常的,匹配 Python id() 函数并匹配地址上的 printf()。
我开始取消注释代码以查看问题可能是什么。问题在于声明:
double nrcs_h_d[MAX_NINC_S*MAX_SCAT_S];
double nrcs_v_d[MAX_NINC_S*MAX_SCAT_S];
如果我注释掉这两行,就不会崩溃。如果我只注释掉第二行,就不会崩溃。但是,如果没有注释掉任何行,它就会崩溃。
奇怪的是 MAX_NINC_S 和 MAX_SCAT_S 都等于 500。所以,这些数组的大小只有几兆字节……在代码的其他地方,几百兆字节的数组分配得很好。
另外,如果我将上面的行替换为:
double *nrcs_h_d, *nrcs_v_d;
nrcs_h_d = (double *)malloc(MAX_NINC_S*MAX_SCAT_S*sizeof(double));
nrcs_v_d = (double *)malloc(MAX_NINC_S*MAX_SCAT_S*sizeof(double));
它似乎工作正常......所以显然问题与试图在堆栈上分配太多有关。
所以,问题变成了:
为什么 gdb 没有显示这是发生分段错误的代码行,而是说它是函数调用?
如果进行了分配,为什么核心转储文件的内存地址似乎全部搞砸了?
谢谢。