0

I'm attempting to wrap a small library I've written in c, and I think I'm on the home stretch to getting it working. The library has some pretty solid tests around it, and I've ran it through valgrind to remove any memory leaks and glaring issues. It works pretty solid on it's own.

However, when I attempt to wrap it using ruby it segfaults. Here's an example project that wraps the library. When the tests in that project are ran, the call to the library segfaults. Running it results in a core abort which I've loaded in gdb to debug, but I'm not sure what's wrong. The core dump says the issue is on this line, but I have no idea what's causing it since the information given is pretty sparse and the code runs well if I run the tests in c land.

The line that the core dump says is segfaulting:

assert( yypParser->yytos!=0 );

You can reproduce it by running rake from the root directory which kicks of a process that ultimately generates a shared object that is loaded by the tests. I'm hoping someone with more experience in c can take a look and potentially point me in the right direction.

Please let me know if any more information is needed.

Snippet from the core dump:

#0  0x00007f150caa2c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007f150caa6028 in __GI_abort () at abort.c:89
#2  0x00007f150dba8d8d in die () at error.c:407
#3  rb_bug_context (ctx=ctx@entry=0x7f150f3b1b80, fmt=fmt@entry=0x7f150dbe2f6a "Segmentation fault at %p") at error.c:437
#4  0x00007f150daa45ce in sigsegv (sig=<optimized out>, info=0x7f150f3b1cb0, ctx=0x7f150f3b1b80) at signal.c:890
#5  <signal handler called>
#6  0x00007f150b96b02b in Parse (yyp=0xf9925e0, yymajor=20, yyminor=..., state=0x7ffe17b6a3a0) at parser.c:1919
#7  0x00007f150b96b8e8 in numerize (data=data@entry=0x7f150b96c1aa "one", state=state@entry=0x7ffe17b6a3a0) at ../../../../ext/example_project/fast_numerizer/fast_numerizer.c:102
#8  0x00007f150b960e0b in example_project_c_code_function () at ../../../../ext/example_project/./example_project.c:11
JesseBuesking
  • 6,496
  • 4
  • 44
  • 89
  • Please [edit] your question to include at least some of the code directly. I'm not going to follow random external links. – Martin Bonner supports Monica Nov 16 '16 at 08:26
  • @MartinBonner I debated adding any code when writing the question, but left it out since I was unsure if it would be of any benefit without more context. I've since included the line that the core dump says is causing the segfault. – JesseBuesking Nov 16 '16 at 08:39
  • Right, so with high probability `yyParser` is null. Options: try inserting `assert(yyParser!=NULL);` on the line before, or run ruby under gdb and step through your code. – Martin Bonner supports Monica Nov 16 '16 at 09:59
  • ... or add lots of debugging printf statements. – Martin Bonner supports Monica Nov 16 '16 at 10:00
  • @MartinBonner I added `assert(yyParser!=NULL);` on the line before, but it's still segfaulting on `assert( yypParser->yytos!=0 );`. It seems as though accessing the property is causing the segfault. I'm confused by the fact that it's suddenly doing this now that it's being called as a ruby extension but continues to work fine as a standalone library. – JesseBuesking Nov 16 '16 at 16:19
  • I compiled your standalone library for x86_64 (once with clang, once with gcc). The compiler showed some warnings, and the code segfaulted reading `yypParser` just as you describe. The segfault did not occur in a 32-bit build. The warnings hint towards the cause of the problem -- calling undeclared functions across file boundaries guesses the types wrong. – RJHunter Nov 18 '16 at 02:17
  • @RJHunter how were you able to control 32/64 bit build? Or were you building just the c library, not the ruby wrapper library? Also, thank you for taking a look! – JesseBuesking Nov 18 '16 at 16:05
  • Just building the C library, no Ruby involved. In my environment, the default build was 64-bit, so a plain old `make` showed the warnings and the segfault. I expect you're seeing a difference in Ruby vs non-Ruby because the two builds use a different compiler command-line (CFLAGS etc). – RJHunter Nov 18 '16 at 21:27
  • 1
    @RJHunter your comment lead me to the solution! The compiler guessed the wrong type, but wouldn't have if the header file for the parser specified the functions defined. `parser.c` is generated by [lemon](http://www.hwaci.com/sw/lemon/) which has an option to make the file compatible with [makeheaders](http://www.hwaci.com/sw/mkhdr/), a program that generates `parser.h` *with* function definitions. Some minor tweaking was necessary to fix up `parser.h`, but once done and linked correctly it no longer has to guess and *presto*, it works! – JesseBuesking Nov 19 '16 at 07:01
  • Taking your code as it is from the github repo I find that it fails to compile from to start with checking for fast_numerizer/fast_numerizer.h... no I look and it's an empty folder. I must have missed something. Getting late and my eyes are tired of reading bright web pages. Do you use darker themes? Most developers do. Can I change this here? – Douglas G. Allen Jan 11 '17 at 01:33

0 Answers0