Hi , the following program segfault with g++3.3 , works with g++2.95 why ????

Discussion in 'C++' started by devesh.agrawal@gmail.com, Oct 8, 2004.

  1. Guest

    Hi , this program does a segfault in g++3.2 onwards , works with
    g++2.95 ,
    Any ideas are welcome , basically there is this instruction when
    compiled with -S option , call *%eax , where the one with 2.95 goes on
    to execude the given machine code , whereas the one compiled in g++3.2
    segfaults.
    Also if you feel , this is not an appropriate group to post this , I
    would be obliged if you could pardon me for the mistake and guide me to
    a better group.

    #include <iostream>
    #include <string>
    using namespace std;
    typedef long (*fptr) (long, long);
    void
    write (string & str)
    {
    str += (char) 0x55;//push %ebp
    str += (char) 0x8B;//mov %esp,%ebp
    str += (char) 0xEC;
    str += (char) 0x8B;//mov 8(%ebp),%eax
    str += (char) 0x45;
    str += (char) 0x08;
    str += (char) 0x03;//add 12(%ebp),%eax
    str += (char) 0x45;
    str += (char) 0x0C;
    str += (char) 0x5D;//pop %ebp
    str += (char) 0xC3;//ret
    }

    main ()
    {
    fptr Func;
    unsigned int val1, val2, retVal;
    string str;
    write (str);
    Func = (fptr) str.c_str ();
    val1 = 123456;
    val2 = 654321;
    retVal = Func (val1, val2);
    cout << "Ans: " << retVal << endl;
    return 0;
    }

    PS : CC the replies to me would be appreciated.
     
    , Oct 8, 2004
    #1
    1. Advertising

  2. Sharad Kala Guest

    <> wrote in message

    > main ()


    The "implicit int" rule of C is no longer supported in C++.

    > {
    > fptr Func;
    > unsigned int val1, val2, retVal;
    > string str;
    > write (str);
    > Func = (fptr) str.c_str ();


    What kind of conversion is this ? You are trying to convert a const char *
    to fptr!

    > val1 = 123456;
    > val2 = 654321;
    > retVal = Func (val1, val2);
    > cout << "Ans: " << retVal << endl;
    > return 0;
    > }
    >
    > PS : CC the replies to me would be appreciated.


    Post here, read here.

    Sharad
     
    Sharad Kala, Oct 8, 2004
    #2
    1. Advertising

  3. Anirudh Guest

    Re: Hi , the following program segfault with g++3.3 , works withg++2.95 why ????

    wrote:
    > Hi , this program does a segfault in g++3.2 onwards , works with
    > g++2.95 ,
    > Any ideas are welcome , basically there is this instruction when
    > compiled with -S option , call *%eax , where the one with 2.95 goes on
    > to execude the given machine code , whereas the one compiled in g++3.2
    > segfaults.
    > Also if you feel , this is not an appropriate group to post this , I
    > would be obliged if you could pardon me for the mistake and guide me to
    > a better group.
    >
    > #include <iostream>
    > #include <string>
    > using namespace std;
    > typedef long (*fptr) (long, long);


    I wrote a simple sum function:
    long sum(long a, long b)
    {
    return a + b;
    }

    The disassembly of this produces the exact same code for
    g++2.95. But for 3.3, there are slight differences.

    > void
    > write (string & str)
    > {
    > str += (char) 0x55;//push %ebp
    > str += (char) 0x8B;//mov %esp,%ebp
    > str += (char) 0xEC;
    > str += (char) 0x8B;//mov 8(%ebp),%eax
    > str += (char) 0x45;
    > str += (char) 0x08;
    > str += (char) 0x03;//add 12(%ebp),%eax
    > str += (char) 0x45;
    > str += (char) 0x0C;
    > str += (char) 0x5D;//pop %ebp


    g++ 3.3 puts a 'leave' instruction instead of 'pop ebp'. But
    leave does pretty much the same thing, I guess. But modifying
    the above to put a leave doesn't seem to work either.

    > str += (char) 0xC3;//ret


    There's also a 'nop' added to the function assembly code
    after the return (in 3.3). Could the segfault be because of
    alignment problems?

    > }
    >
    > main ()
    > {
    > fptr Func;
    > unsigned int val1, val2, retVal;
    > string str;
    > write (str);
    > Func = (fptr) str.c_str ();


    I'm relatively a newbie, but I read somewhere that assigning a data item
    to a function pointer like the above invokes undefined behaviour. Could
    that be the reason that compilers behave differently?

    > val1 = 123456;
    > val2 = 654321;
    > retVal = Func (val1, val2);
    > cout << "Ans: " << retVal << endl;
    > return 0;
    > }
    >
    > PS : CC the replies to me would be appreciated.
    >


    Basically, I'm stumped too. Maybe someone else can find out where I
    didn't think hard enough.


    -- Anirudh
     
    Anirudh, Oct 8, 2004
    #3
  4. Anirudh Guest

    Re: Hi , the following program segfault with g++3.3 , works withg++2.95 why ????

    Anirudh wrote:
    > wrote:
    > > Hi , this program does a segfault in g++3.2 onwards , works with
    > > g++2.95 ,
    > > Any ideas are welcome , basically there is this instruction when
    > > compiled with -S option , call *%eax , where the one with 2.95 goes on
    > > to execude the given machine code , whereas the one compiled in g++3.2
    > > segfaults.
    > > Also if you feel , this is not an appropriate group to post this , I
    > > would be obliged if you could pardon me for the mistake and guide me to
    > > a better group.
    > >
    > > #include <iostream>
    > > #include <string>
    > > using namespace std;
    > > typedef long (*fptr) (long, long);

    >
    > I wrote a simple sum function:
    > long sum(long a, long b)
    > {
    > return a + b;
    > }
    >
    > The disassembly of this produces the exact same code for
    > g++2.95. But for 3.3, there are slight differences.
    >


    Sorry, the 'long' should be replaced with 'int' to produce
    the code below. Otherwise, everything turns out to be pushl,
    popl etc...

    > > void
    > > write (string & str)
    > > {
    > > str += (char) 0x55;//push %ebp
    > > str += (char) 0x8B;//mov %esp,%ebp
    > > str += (char) 0xEC;
    > > str += (char) 0x8B;//mov 8(%ebp),%eax
    > > str += (char) 0x45;
    > > str += (char) 0x08;
    > > str += (char) 0x03;//add 12(%ebp),%eax
    > > str += (char) 0x45;
    > > str += (char) 0x0C;
    > > str += (char) 0x5D;//pop %ebp

    >
    > g++ 3.3 puts a 'leave' instruction instead of 'pop ebp'. But
    > leave does pretty much the same thing, I guess. But modifying
    > the above to put a leave doesn't seem to work either.
    >
    > > str += (char) 0xC3;//ret

    >
    > There's also a 'nop' added to the function assembly code
    > after the return (in 3.3). Could the segfault be because of
    > alignment problems?
    >
    > > }
    > >
    > > main ()
    > > {
    > > fptr Func;
    > > unsigned int val1, val2, retVal;
    > > string str;
    > > write (str);
    > > Func = (fptr) str.c_str ();

    >
    > I'm relatively a newbie, but I read somewhere that assigning a data item
    > to a function pointer like the above invokes undefined behaviour. Could
    > that be the reason that compilers behave differently?
    >
    > > val1 = 123456;
    > > val2 = 654321;
    > > retVal = Func (val1, val2);
    > > cout << "Ans: " << retVal << endl;
    > > return 0;
    > > }
    > >
    > > PS : CC the replies to me would be appreciated.
    > >

    >
    > Basically, I'm stumped too. Maybe someone else can find out where I
    > didn't think hard enough.
    >
    >
    > -- Anirudh
    >


    -- Anirudh
     
    Anirudh, Oct 8, 2004
    #4
  5. Michael Kurz Guest

    <> schrieb im Newsbeitrag
    news:...
    >
    > main ()
    > {
    > fptr Func;
    > unsigned int val1, val2, retVal;
    > string str;
    > write (str);
    > Func = (fptr) str.c_str ();
    > val1 = 123456;
    > val2 = 654321;
    > retVal = Func (val1, val2);
    > cout << "Ans: " << retVal << endl;
    > return 0;
    > }
    >
    > PS : CC the replies to me would be appreciated.
    >


    Which OS are you working on?
    => are you allowd to execut code within the address space your code is in?
    (In Windows: VirtualProtect(..) )
    perhapes try a simple ret. I tried on my debian linux so I guess its a
    problem with the memory permissions, or the segment descriptors. Im not so
    familiy with this stuff on linux (I only used to work with it on windows).

    But when I placed the code on the stack it worked. Your sample places the
    code on the heap (new) as this is the function std::string::c_str() is
    probably using. If you would use data on the stack or even global it should
    work.


    Regards
    Michael

    <snip>


    char gByte = 0xC3;

    int main(){
    // Failed as I guess the no execution on the heaps address space. (even
    the segment descriptors could be different)
    std::string fct_code = "0xC3";
    LPFN_Func Func = (LPFN_Func)fct_code.c_str();
    Func();

    // Worked on my machine P4, gcc 3.3.4 debian
    char byte = 0xC3;
    LPFN_Func Func2 = (LPFN_Func)&byte;
    Func2();

    // Worked on my machine P4, gcc 3.3.4 debian
    LPFN_Func Func3 = (LPFN_Func)&gByte;
    Func3();

    }




    </snip>
     
    Michael Kurz, Oct 8, 2004
    #5
  6. Ron Natalie Guest

    Re: Hi , the following program segfault with g++3.3 , works withg++2.95 why ????

    Sharad Kala wrote:
    > <> wrote in message
    >
    >
    >>main ()

    >
    >
    > The "implicit int" rule of C is no longer supported in C++.
    >


    nor in C.
    >
     
    Ron Natalie, Oct 8, 2004
    #6
  7. Jack Klein Guest

    On 8 Oct 2004 01:08:36 -0700, wrote in
    comp.lang.c++:

    > Hi , this program does a segfault in g++3.2 onwards , works with
    > g++2.95 ,
    > Any ideas are welcome , basically there is this instruction when
    > compiled with -S option , call *%eax , where the one with 2.95 goes on
    > to execude the given machine code , whereas the one compiled in g++3.2
    > segfaults.
    > Also if you feel , this is not an appropriate group to post this , I
    > would be obliged if you could pardon me for the mistake and guide me to
    > a better group.
    >
    > #include <iostream>
    > #include <string>
    > using namespace std;
    > typedef long (*fptr) (long, long);
    > void
    > write (string & str)
    > {
    > str += (char) 0x55;//push %ebp
    > str += (char) 0x8B;//mov %esp,%ebp
    > str += (char) 0xEC;
    > str += (char) 0x8B;//mov 8(%ebp),%eax
    > str += (char) 0x45;
    > str += (char) 0x08;
    > str += (char) 0x03;//add 12(%ebp),%eax
    > str += (char) 0x45;
    > str += (char) 0x0C;
    > str += (char) 0x5D;//pop %ebp
    > str += (char) 0xC3;//ret
    > }
    >
    > main ()
    > {
    > fptr Func;
    > unsigned int val1, val2, retVal;
    > string str;
    > write (str);
    > Func = (fptr) str.c_str ();


    [snip]

    This line is completely illegal in either C or C++. There is
    absolutely no conversion defined at all between pointers to functions
    and pointers to objects.

    The behavior of this code is completely undefined. Whatever happens
    once you execute the last line above is not a matter for the C++
    language at all. It does not specify, nor does it care.

    Either stop writing such nonsense, or take it to a compiler specific
    support group. It is not a language issue because you have violated
    the rules of the language.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Oct 9, 2004
    #7
  8. Michael Kurz Guest

    "Jack Klein" <> schrieb im Newsbeitrag
    news:...
    > On 8 Oct 2004 01:08:36 -0700, wrote in
    > comp.lang.c++:
    >
    > >
    > > main ()
    > > {
    > > fptr Func;
    > > unsigned int val1, val2, retVal;
    > > string str;
    > > write (str);
    > > Func = (fptr) str.c_str ();

    >
    > [snip]
    >
    >
    > Either stop writing such nonsense, or take it to a compiler specific
    > support group. It is not a language issue because you have violated
    > the rules of the language.
    >


    I would say its definitely not nonsense, and even if so, telling someone
    with these words sounds not very polite to me.
    IMHO it's quite similar to a downcast or all other constructs where the
    compiler does not have the type information anymore and its completely in
    the hands
    of the programmer to know what he is doing. I can agree that such situations
    should be avoided if possible but if not, I'd say it always was a strength
    of C to allow
    such things and so it is in C++.


    > --
    > Jack Klein
    > Home: http://JK-Technology.Com
    > FAQs for
    > comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    > comp.lang.c++ http://www.parashift.com/c -faq-lite/
    > alt.comp.lang.learn.c-c++
    > http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Michael Kurz, Oct 9, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    922
    Mark Rae
    Dec 21, 2006
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,077
    Smokey Grindel
    Dec 2, 2006
  3. aditya

    how the following printf statement works

    aditya, Oct 29, 2004, in forum: C Programming
    Replies:
    9
    Views:
    474
    Joona I Palaste
    Oct 29, 2004
  4. Andrey Vul
    Replies:
    8
    Views:
    698
    Richard Bos
    Jul 30, 2010
  5. smith jack
    Replies:
    1
    Views:
    191
    TheSaint
    Jul 10, 2011
Loading...

Share This Page