From: Paul C Date: 2001-03-13T13:40:04+09:00 Subject: [ruby-talk:12540] Strange segmentation fault problem with C++ extension Hi, I have been beating my head against the monitor for a couple of days with a repeatable segmentation problem with a C++ extension - I am sure that there is something obvious that I am missing and would be grateful for any advice. I am trying to create a Ruby wrapper for the ZIPIOS C++ Zip file reader library (http://zipios.sourceforge.net). I managed to get this mostly working however I have been stuck with a deterministic problem with the extension core dumping in the method to extract a zip file entry under the following conditions - - Running under IRB - Calling the method without a 'begin/rescue' block (ie caught interactively by IRB) - (Optional) Call the method with a filename which exists in archive -> OK - Call the method with a filename which does not exist in the archive -> Throws an exception - Call the method with a filename which does exist -> Core Dump If the failing method call is enclosed in a begin/rescue block the problem goes away (which would always be the case outside the interactive shell). If the method is called multiple times with a valid entry or even multiple times with an invalid entry it works fine - it is just the sequence invalid/valid which causes the program to crash. Unfortunately I am not a C++ programmer (and following this experience have no desire to become one) so I would ask you to excuse the code - however I wasnt able to find a C Zip file library. I am concerned that there is an underlying problem in the code somewhere which is causing this but havent been able to make any progress (I will of course be releasing the module to the RAA once I get this fixed). I have instrumented the module and the strange thing is that there is no apparent difference in the calling sequence between a method that succeeds and a subsequent method that causes a segmentation fault (after an intervening request for an non-existant entry). The source code for the method that is failing is at the end of the message - if anyone would like the source code to the whole extension please let me know and I will e-mail it. The debug trace below is equivalent for the first/third calls (which should be the same without the failing call between them). The final debug print of the return VALUE is generated immediately before the method returns and shows the the VALUE to be returned has been created successfully within the method. The method segemntation faults when the functio tries to return the VALUE. I am at a loss as to why this happens - any suggestions ? Regards, Paul PS. I forgot the obligatory thanks to Matz and the Ruby community for a great language - it is a pleasure to use (and hopefully extend if I can get this !#$&&*# module working!) PPS. Versions are - Ruby 1.6.3 / NetBSD 1.5 =========== DEBUG TRACE =========== # irb --prompt xmp require 'Zip' ==>true z = Zip::ZipFile.new "test.zip" ==># z.entries { |e| print e.path, "\n" } # Get Zip Directory extconf.rb Makefile ==># z.entry "extconf.rb" # OK (zip.cpp:186) MSG: Entering Function #ZipFile_entry (zip.cpp:187) VALUE: self -> # (zip.cpp:191) PTR: ZipFile ->135501760 (zip.cpp:201) MSG: GetEntry OK (zip.cpp:203) PTR: ConstEntryPointer ->135870784 (zip.cpp:205) VALUE: zipLocalEntry -> # ==># z.entry "zzzzzzz" # Invalid Entry (zip.cpp:186) MSG: Entering Function #ZipFile_entry (zip.cpp:187) VALUE: self -> # (zip.cpp:191) PTR: ZipFile ->135501760 (zip.cpp:196) MSG: GetEntry Failed RuntimeError: Entry not found (irb):10:in `entry' (irb):10:in `irb_binding' z.entry "extconf.rb" # Should be OK (zip.cpp:186) MSG: Entering Function #ZipFile_entry (zip.cpp:187) VALUE: self -> # (zip.cpp:191) PTR: ZipFile ->135501760 (zip.cpp:201) MSG: GetEntry OK (zip.cpp:203) PTR: ConstEntryPointer ->136008256 (zip.cpp:205) VALUE: zipLocalEntry -> # (irb):12: [BUG] Segmentation fault ruby 1.6.3 (2001-03-07) [i386-netbsd1.5] Abort (core dumped) =========== METHOD SOURCE =========== static VALUE ZipFile_entry ( VALUE self, VALUE name ) { VALUE zipLocalEntry = Qnil ; ConstEntryPointer entry ; ConstEntryPointer *ptr_entry ; ZipFile *zf ; const string sname = STR2CSTR(name) ; DEBUG_MSG("Entering Function #ZipFile_entry") ; DEBUG_VALUE("self",self) ; Get_ZipFile ( self, zf ) ; DEBUG_PTR("ZipFile",zf) ; try { if ( (entry = zf->getEntry(sname)) == 0 ) { DEBUG_MSG("GetEntry Failed") ; rb_raise ( rb_eRuntimeError, "Entry not found" ) ; } else { DEBUG_MSG("GetEntry OK") ; ptr_entry = new ConstEntryPointer ( entry ) ; DEBUG_PTR("ConstEntryPointer",ptr_entry) ; zipLocalEntry = ZipLocalEntry_new ( ptr_entry ) ; DEBUG_VALUE("zipLocalEntry",zipLocalEntry) ; return zipLocalEntry ; } } catch ( exception &excp ) { DEBUG_MSG("Exception") ; rb_raise ( rb_eRuntimeError, excp.what() ) ; } }