简体   繁体   English

PHP扩展中的SEG错误

[英]SEG Fault in PHP extension

I wrote a PHP extension to access functions in a static lib, I built PHP as a CGI, and everything seemed to work (after days of working on it..) 我写了一个PHP扩展来访问静态库中的函数,我将PHP构建为CGI,并且一切似乎都可以正常工作(经过几天的努力。)

Thrilled once everything worked, I re-compiled PHP without debugging messages I had in it. 一旦一切正常,我很激动,我重新编译了PHP,却没有调试其中的消息。 ( php_printf("here111"); .... php_printf("sending arguments..."); ) php_printf("here111"); .... php_printf("sending arguments...");

Then, it just stopped working. 然后,它停止工作了。 The function I'm calling in the static lib works, I've tested it by calling it directly from another executable. 我在静态库中调用的函数有效,我已经通过直接从另一个可执行文件调用它来对其进行了测试。

I built PHP with debugging symbols ( --enable-debug ) and can debug it to a certain degree in gdb. 我用调试符号( --enable-debug )构建了PHP,并可以在gdb中对其进行一定程度的调试。

I'm still struggling to figure out what's wrong. 我仍在努力找出问题所在。 It seems that the function in the lib ( diffFst ) cannot seem to read the input arguments. 似乎lib( diffFst )中的函数似乎无法读取输入参数。

268     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssssssd",
269        &filA, &filA_len,
270        &nomvarA, &nomvarA_len,
271        &filB, &filB_len,
272        &nomvarB, &nomvarB_len,
273        &filO, &filO_len,
274        &newnomvar, &newnomvar_len,
275        &mult
276        ) == FAILURE) {
277         RETURN_LONG(-100);
278     }
279 
280     php_printf("Read arguments:\nfilA: %s, nomvara: %s\nfilB: %s, nomvarB: %s\nfilO: %s, nomvarO: %s\nMult: %0.3f\n",
281        filA,nomvarA, filB,nomvarB, filO,newnomvar, mult);
282 
285     ier = difffst_(filA,nomvarA, filB,nomvarB, filO,newnomvar, mult);

When I call this function, the php_printf() statement works and prints out the right values. 当我调用此函数时, php_printf()语句起作用并打印出正确的值。 When I let it call the difffst_ function however, I get a segfault when it tries to read the input variables. 但是,当我让它调用difffst_函数时,当它尝试读取输入变量时会出现段错误。

The diffFst function is written in fortran: diffFst函数用fortran编写:

  5 function diffFst(filA, nomvara, filB, nomvarb, filO, newnomvar, change, write_tictac, in_verbose) result(ier)
 10     implicit none
 11 

 12     character (len=*), intent(IN) :: filA, filB, filO
 13     character (len=*), intent(IN) :: nomvara, nomvarb, newnomvar
 14 
 16     real, intent(IN) :: change
 17     logical, intent(IN) :: write_tictac
 18 
 19     logical, intent(IN), optional :: in_verbose
 21     logical :: verbose = .false.
 27     integer :: ier
...
117     ier = fstouv(iuna, 'RND')
118     IF (ier < 0) THEN
119         if (verbose) write(stderr,'(2A)') "Could not fstouv FST file ", trim(filA)
120     ELSE
121         nmax = fstnbr(iuna);
122         if (verbose) write(stdout,'(3A,I6,A)') "Succesfully opened ", trim(filA), ' with ', nmax, ' records'
123         allocate(liste(nmax))
124     END IF

Specifically, it fails at line 122 (according to the debugger) when it tries to read filA . 具体来说,当它尝试读取filA时,它在第122行失败(根据调试器)。

I have no idea why, I've tried: 我不知道为什么,我试过了:

  • Making the function a subroutine 使函数成为子例程
  • Making the function a fortran function 使函数成为fortran函数
  • Making the function a 'pure' function 使函数成为“纯”函数
  • Having return values (that's what is there now, the ier = .. ) 具有返回值(现在就是那里, ier = ..
  • Having return statements in the code, removing the return statements return语句中的代码,去掉return报表
  • Tried printing things out to stdout, and to log files 尝试将内容打印到标准输出和日志文件

It just seems like the data isn't being passed properly. 似乎数据没有正确传递。 Even in the debugger, I can't read the arguments. 即使在调试器中,我也无法读取参数。

The frustrating thing is, at one point this just worked.. I've checked file permissions, checked paths, etc.. And I can run the function from a fortran wrapper executable just fine. 令人沮丧的是,在某一点上它确实起作用了。我检查了文件许可权,检查了路径等。而且我可以从fortran包装可执行文件运行该函数。

Is there a trick I'm missing? 我有想念的招吗?

Thanks 谢谢

Took a while, and needed additional help ( issues like this ) 花了一段时间,并且需要其他帮助( 类似这样的问题

Basically two things had to change: 基本上必须改变两件事:

  • Pass integers by reference 通过引用传递整数
  • Accept strings properly 正确接受字符串

The first is easy, simply ier=func(..., &integer_var, ...) 第一个很简单,只需ier=func(..., &integer_var, ...)

The second involved passing the length of the string. 第二个涉及传递字符串的长度。 There may have been an easier way to do this (sensing string length by looking for the \\0) but they didn't work out. 可能有一种更简单的方法(通过查找\\ 0来检测字符串的长度),但是它们没有解决。 So, now I pass 所以,现在我通过

ier = func(str,strlen,...)

Then in Fortran, I accept the string as 然后在Fortran中,我接受字符串为

character(kind=c_char,len=strlen), intent(IN) :: str

The specific changes to the fortran code above are 上面的fortran代码的特定更改是

11     use, intrinsic :: iso_c_binding
12     use interfaces_rmnutils
13     implicit none
16     integer(kind=c_int), intent(IN) :: len_filA, len_filB, len_filO
17     character (kind=c_char,len=len_filA), intent(IN) :: filA
18     character (kind=c_char,len=len_filB), intent(IN) :: filB
19     character (kind=c_char,len=len_filO), intent(IN) :: filO

When it was working, it must have been before I attempted to read in the strings as (len=*) , and integers were being passed in as references, so they'd have had random values essentially. 当它正常工作时,一定是在我尝试将字符串读为(len=*) ,并且整数已经作为引用传入,因此它们本质上具有随机值。

Thanks for everyone's else! 谢谢其他人!

Your program, seems, currupts the stack. 您的程序似乎破坏了堆栈。 Stack corruption usually comes with improper usage of pointers. 堆栈损坏通常伴随着不正确的指针使用。 Check carefully (investigate contents of variables using debugger or simple footprints) right before suspicious function calls. 在调用可疑函数之前,请仔细检查(使用调试器或简单的脚印调查变量的内容)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM