Help? seg-fault...

View: New views
6 Messages — Rating Filter:   Alert me  

Help? seg-fault...

by Michael Wieher :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

hey all.
I'm pretty new to using memcached, but have already found it
incredibly powerful.

I don't run into any problems using it, but when my program exits, it
dies with a seg-fault.

If  I comment this function out, there is no seg-fault:

    int getCachedRequest(char* ans,char* req,iniData* data) {
        memcached_return mcr;
        uint32_t flags;
        size_t size;
        char * cp;
        cp = memcached_get(&(data->mc),req,strlen(req),&size,&flags,&mcr);
        if(mcr==0) {
            memcpy(ans,cp,strlen(cp));
            free(cp);cp=NULL;
            return 1;
        }
        free(cp);cp=NULL;
        return 0;
    }


if I use it, there is.
any suggestions on how or why to diagnose the problem?
as you can see, I have a structure "iniData data" that holds a pointer
to the memcached_st
....
its pretty simple, straightforward, and as I say, no problems during
execution, works beautifully, but when exiting, something in the
cleanup behind the scenes gets confused and segfaults out.
its nothing a call to _exit() won't .... "fix" but I'd really rather
avoid that if I can.

Thanks,
-mike

Re: Help? seg-fault...

by Dustin Sallings :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Jul 1, 2008, at 12:29, Michael Wieher wrote:

       cp = memcached_get(&(data->mc),req,strlen(req),&size,&flags,&mcr);
       if(mcr==0) {
           memcpy(ans,cp,strlen(cp));

Are you completely sure it's safe to call strlen on whatever cp is?  Just use the size.

In general, running stuff like this through valgrind will tell you a lot.

-- 
Dustin Sallings


Re: Help? seg-fault...

by Michael Wieher :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks.
Yeah, I'm using size now, I've tried it both ways.  'size' is of
course more reliable.

Valgrind did not turn up anything useful that I could find..  a number
of errors like this:

==12359== Invalid read of size 4
==12359==    at 0x40B8934: _IO_flush_all_lockp (in /lib/libc-2.5.so)
==12359==    by 0x40B94EF: _IO_cleanup (in /lib/libc-2.5.so)
==12359==    by 0x4081812: exit (in /lib/libc-2.5.so)
==12359==    by 0x406BDF3: (below main) (in /lib/libc-2.5.so)
==12359==  Address 0x41DAACC is not stack'd, malloc'd or (recently) free'd

that end like this

==12359== Process terminating with default action of signal 11
(SIGSEGV): dumping core
==12359==  Access not within mapped region at address 0xC
==12359==    at 0x40B8946: _IO_flush_all_lockp (in /lib/libc-2.5.so)
==12359==    by 0x40B94EF: _IO_cleanup (in /lib/libc-2.5.so)
==12359==    by 0x4081812: exit (in /lib/libc-2.5.so)
==12359==    by 0x406BDF3: (below main) (in /lib/libc-2.5.so)
==12359==
==12359== Process terminating with default action of signal 11 (SIGSEGV)
==12359==  Access not within mapped region at address 0xC
==12359==    at 0x40B8946: _IO_flush_all_lockp (in /lib/libc-2.5.so)
==12359==    by 0x40B94EF: _IO_cleanup (in /lib/libc-2.5.so)
==12359==    by 0x41624C0: __libc_freeres (in /lib/libc-2.5.so)
==12359==    by 0x40011E6: _vgnU_freeres (vg_preloaded.c:60)
==12359==    by 0x41DAA37: ???
==12359==    by 0x40B94EF: _IO_cleanup (in /lib/libc-2.5.so)
==12359==    by 0x4081812: exit (in /lib/libc-2.5.so)
==12359==    by 0x406BDF3: (below main) (in /lib/libc-2.5.so)


It LOOKS to me as if the code is trying to read (multiple) memory
addresses that are "not stack'd, malloc'd, or free'd"
...and my best guess is that its trying to free memory it thinks needs
to be cleaned up on exit but somehow has already been.

It will ALSO segfault (on exit, again, not during regular execution,
if I include this bit of code

    //---- MEMCACHED SET
    extern iniData data;
    char qstring[32];
    uint32_t flags=0;
    sprintf(qstring,"%s%d%lu",code,cur->file,cur->location);
    char * tempbuff = (char*)calloc(sizeof(char),cur->size);
    memcpy(tempbuff,(char*)cCom,cur->size);
    memcached_set(&(data.mc),qstring,strlen(qstring),tempbuff,cur->size,(time_t)0,flags);
    free(tempbuff);tempbuff=NULL;
    //---- END MEMCACHED SET STUFF */

I'm only using valgrind's memory checker.. maybe I'll dig around with
some of their other tools and see what I can find.

On Tue, Jul 1, 2008 at 2:43 PM, Dustin Sallings <dustin@...> wrote:

>
> On Jul 1, 2008, at 12:29, Michael Wieher wrote:
>
>        cp = memcached_get(&(data->mc),req,strlen(req),&size,&flags,&mcr);
>        if(mcr==0) {
>            memcpy(ans,cp,strlen(cp));
>
> Are you completely sure it's safe to call strlen on whatever cp is?  Just
> use the size.
>
> In general, running stuff like this through valgrind will tell you a lot.
>
> --
> Dustin Sallings
>

Re: Help? seg-fault...

by Dustin Sallings :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Jul 1, 2008, at 13:03, Michael Wieher wrote:

(a few spaces would make this easier to read)

   sprintf(qstring,"%s%d%lu",code,cur->file,cur->location);

sprintf is generally not recommended.  It doesn't seem terribly hard to get it to exceed your stack buffer here.

It would be valuable at least to check the return value to ensure it is strictly less than the size of your buffer.

An assert(strlen(qstring) < sizeof(qstring)) would also help with that.

   char * tempbuff = (char*)calloc(sizeof(char),cur->size);

assert(tempbuff);


You seem to be missing symbols from the valgrind output.  Perhaps you should compile the debugging symbols in.

-- 
Dustin Sallings


Re: Help? seg-fault...

by Michael Wieher :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

>
>    sprintf(qstring,"%s%d%lu",code,cur->file,cur->location);
>
> sprintf is generally not recommended.  It doesn't seem terribly hard to get
> it to exceed your stack buffer here.

It is a guarantee that "code" is never more than 8 characters, file
ranges from 2-digits to 3, max, and location wouldn't ever be more
than 10 characters.  So, I'm looking at a string of max 21 chars, I
made it 32.
These inputs come from controlled static sources, not user input.
However I did recompile w/asserts and they passed w/o issues.

> You seem to be missing symbols from the valgrind output.  Perhaps you should
> compile the debugging symbols in.

I know.  It's a bit of a strange situation, in that I'm actually
compiling a shared-library.so file that is imported into and run by
Python, but the compilation itself of the C++ library is done with -g
... so I'm at a bit of a loss as how to get a different angle on it,
without basically writing a wrapper-driver to compile & test the
sucker at the C/C++ level, before then wrapping it into Python.

thanks though...

Re: Help? seg-fault...

by Dustin Sallings :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Jul 1, 2008, at 13:35, Michael Wieher wrote:

> It is a guarantee that "code" is never more than 8 characters,

        That's not a guarantee.  snprintf is a guarantee.

> file
> ranges from 2-digits to 3, max, and location wouldn't ever be more
> than 10 characters.  So, I'm looking at a string of max 21 chars, I
> made it 32.
>
> These inputs come from controlled static sources, not user input.
> However I did recompile w/asserts and they passed w/o issues.

        I can't say for sure what's going on in your code without seeing it  
as a whole, but these kinds of things are smells.  Any place you  
assume something, just stick an assertion in the code to both document  
and enforce it.  Makes it a lot harder to write bugs.

>> You seem to be missing symbols from the valgrind output.  Perhaps  
>> you should
>> compile the debugging symbols in.
>
> I know.  It's a bit of a strange situation, in that I'm actually
> compiling a shared-library.so file that is imported into and run by
> Python, but the compilation itself of the C++ library is done with -g
> ... so I'm at a bit of a loss as how to get a different angle on it,
> without basically writing a wrapper-driver to compile & test the
> sucker at the C/C++ level, before then wrapping it into Python.

        Yeah, definitely test the parts in the most simple way possible.  
You've got a really simple error somewhere.  The less code you have to  
look at, the easier it'll be to find.

        See also:  The Underhaded C Contest.  :)

--
Dustin Sallings