Function call problems (64-bit)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Max

    #1

    Function call problems (64-bit)

    Warning: newbie question!
    If I have a function (translated from fortran using f2c)

    int fun1(integer *n, doublereal *x)
    {
    integer m, i;

    m = (*n);
    for(i = 0; i < m; i++)
    x[i] = 0.;

    return 0;
    }

    where (from f2c.h)

    typedef long int integer;
    typedef double doublereal;


    Then I use it in a C program written from scratch:

    < all include files here>

    int main()
    {
    int n = 5;
    double *x = malloc(n * sizeof(doublere al));
    int retval;

    retval = fun1((integer &)n, x);

    return 0;
    }


    I get segmentation fault on 64-bit architecture. The problem is that n
    is not passed correctely to fun1, even with a cast. Defining in main()

    integer n = 5

    then it works. A more elegant solution?

    Thanks
    Max

  • Bjørn Augestad

    #2
    Re: Function call problems (64-bit)

    Max wrote:[color=blue]
    > Warning: newbie question!
    > If I have a function (translated from fortran using f2c)
    >
    > int fun1(integer *n, doublereal *x)
    > {
    > integer m, i;
    >
    > m = (*n);
    > for(i = 0; i < m; i++)
    > x[i] = 0.;
    >
    > return 0;
    > }
    >
    > where (from f2c.h)
    >
    > typedef long int integer;
    > typedef double doublereal;
    >
    >
    > Then I use it in a C program written from scratch:
    >
    > < all include files here>
    >
    > int main()
    > {
    > int n = 5;[/color]

    integer n = 5;
    [color=blue]
    > double *x = malloc(n * sizeof(doublere al));[/color]

    doublereal* x = malloc(n * sizeof *x);[color=blue]
    > int retval;
    >
    > retval = fun1((integer &)n, x);[/color]
    retval = fun1(&n, x);[color=blue]
    >
    > return 0;
    > }
    >
    >
    > I get segmentation fault on 64-bit architecture. The problem is that n
    > is not passed correctely to fun1, even with a cast. Defining in main()
    >
    > integer n = 5
    >
    > then it works. A more elegant solution?[/color]

    Use the defined data types(integer, doublereal). Your problem is
    probably that sizeof(int) != sizeof(long int).

    HTH
    Bjørn

    [color=blue]
    >
    > Thanks
    > Max
    >[/color]

    Comment

    • Richard Heathfield

      #3
      Re: Function call problems (64-bit)

      Max said:
      [color=blue]
      > Warning: newbie question!
      > If I have a function (translated from fortran using f2c)
      >
      > int fun1(integer *n, doublereal *x)
      > {
      > integer m, i;
      >
      > m = (*n);
      > for(i = 0; i < m; i++)
      > x[i] = 0.;
      >
      > return 0;
      > }
      >
      > where (from f2c.h)
      >
      > typedef long int integer;
      > typedef double doublereal;
      >
      >
      > Then I use it in a C program written from scratch:
      >
      > < all include files here>
      >
      > int main()
      > {
      > int n = 5;
      > double *x = malloc(n * sizeof(doublere al));
      > int retval;
      >
      > retval = fun1((integer &)n, x);
      >
      > return 0;
      > }
      >
      >
      > I get segmentation fault on 64-bit architecture.[/color]

      If you got the above code to compile without diagnostics, you're not using a
      C compiler. A diagnostic is required for the line:

      retval = fun1((integer &)n, x);

      --
      Richard Heathfield
      "Usenet is a strange place" - dmr 29/7/1999

      email: rjh at above domain (but drop the www, obviously)

      Comment

      • Mike Wahler

        #4
        Re: Function call problems (64-bit)

        "Max" <iprmaster@gmai l.com> wrote in message
        news:1132738540 .951720.9650@g4 3g2000cwa.googl egroups.com...[color=blue]
        > Warning: newbie question!
        > If I have a function (translated from fortran using f2c)
        >
        > int fun1(integer *n, doublereal *x)
        > {
        > integer m, i;
        >
        > m = (*n);
        > for(i = 0; i < m; i++)[/color]

        Beware! If the address of a negative value is passed for 'n',
        this loop will cause 'i' to overflow, giving undefined behavior.
        [color=blue]
        > x[i] = 0.;[/color]
        [color=blue]
        >
        > return 0;
        > }
        >
        > where (from f2c.h)
        >
        > typedef long int integer;
        > typedef double doublereal;
        >
        >
        > Then I use it in a C program written from scratch:
        >
        > < all include files here>
        >
        > int main()
        > {
        > int n = 5;
        > double *x = malloc(n * sizeof(doublere al));[/color]

        What if the allocation fails?
        [color=blue]
        > int retval;
        >
        > retval = fun1((integer &)n, x);[/color]

        This is a syntax error. Presumably you meant:
        retval = fun1(&n, x);
        [color=blue]
        >[/color]

        free(x);
        [color=blue]
        > return 0;
        > }
        >
        >
        > I get segmentation fault on 64-bit architecture. The problem is that n
        > is not passed correctely to fun1,[/color]

        Yes, that's the problem. The problem that needs to be fixed.
        [color=blue]
        > even with a cast.[/color]

        Many people suffer from the misconception that a cast will
        somehow magically let one safely violate the rules. All it
        typically does is stop a compiler from warning you that your
        gun is pointing at your foot and the safety is off.
        [color=blue]
        > Defining in main()
        >
        > integer n = 5
        >
        > then it works.[/color]

        I works when doing that because then you're following the rules.
        [color=blue]
        > A more elegant solution?[/color]

        One of our comp.lang.c denizens once remarked: (paraphrased)
        "Lie to your compiler, and it will get its revenge".
        He's right.

        Elegant solution: Forget 'elegant', concentrate on 'solution'.
        Solution: Don't Lie.

        It appears that for your implementation, the sizes and/or
        representations of types 'int' and 'long int' are not the
        same. When you pass the address of (main()'s) 'n', 'fun1()',
        when dereferencing understandably gets it wrong, probably
        trying to access memory not part of the object 'n' in 'main()'.
        (But officially, the behavior is simply 'undefined' meaning
        that anything might happen).

        The cleanest solution is to stop passing a pointer and pass
        'n' by value directly (the language already defines a built
        in conversion from type 'int' to 'long int'.

        int fun1(long int n, double *x)
        {
        /* etc */
        }

        int main()
        {
        int n = 5;
        double *x = malloc(n * sizeof *x);
        if(x)
        {
        fun1(n, x);
        free(x);
        }
        return 0;
        }

        Why that 'f2c' converter needs to use those typedefs I don't
        know. IMO they're just obfuscating clutter. C already has perfectly
        good type names. Also I'm suspicious of any code 'converted'
        by automation. Often the languages involved have sufficient
        differences in semantics that the target language is not exploited
        effectively, often leading to buggy and/or poor performing,
        at best unreadable, code.

        -Mike


        Comment

        • Max

          #5
          Re: Function call problems (64-bit)

          Sorry, I have just generated this example for posting The correct line
          is

          retval = fun1((integer *)&n, x);

          and no warnings nor errors should arise with gcc-3.4 -Wall.

          Comment

          • Max

            #6
            Re: Function call problems (64-bit)

            Thanks for the good tips (especially for the remark). Anyway, such
            f2c-translated routines are not under my control, therefore I have to
            use them as they are. As you have said, the conversion between "int"
            and "long int" is included in the language specification, therefore
            this should be the solution

            int n = 5;
            integer n1 = n;

            retval = fun1(n1, x);

            For the other remarks: this program is just an example, malloc is
            checked and argument are always positive...
            Anyway, thanks for your help

            Comment

            • Mike Wahler

              #7
              Re: Function call problems (64-bit)


              "Max" <iprmaster@gmai l.com> wrote in message
              news:1132742879 .579858.146620@ f14g2000cwb.goo glegroups.com.. .[color=blue]
              > Sorry, I have just generated this example for posting The correct line
              > is
              >
              > retval = fun1((integer *)&n, x);
              >
              > and no warnings nor errors should arise with gcc-3.4 -Wall.[/color]

              Absence of compiler errors does not at all
              guarantee correct run time behavior.

              The above *might* work, but it's equally possible
              (I think probable) that it will not. There's no
              guarantee from the language that it will.

              -Mike


              Comment

              • pete

                #8
                Re: Function call problems (64-bit)

                Max wrote:[color=blue]
                >
                > Warning: newbie question!
                > If I have a function (translated from fortran using f2c)
                >
                > int fun1(integer *n, doublereal *x)
                > {
                > integer m, i;
                >
                > m = (*n);
                > for(i = 0; i < m; i++)
                > x[i] = 0.;
                >
                > return 0;
                > }
                >
                > where (from f2c.h)
                >
                > typedef long int integer;
                > typedef double doublereal;[/color]

                I dislike reading code like that.
                [color=blue]
                >
                > Then I use it in a C program written from scratch:
                >
                > < all include files here>
                >
                > int main()
                > {
                > int n = 5;
                > double *x = malloc(n * sizeof(doublere al));
                > int retval;
                >
                > retval = fun1((integer &)n, x);
                >
                > return 0;
                > }
                >
                > I get segmentation fault on 64-bit architecture. The problem is that n
                > is not passed correctely to fun1, even with a cast. Defining in main()
                >
                > integer n = 5
                >
                > then it works. A more elegant solution?[/color]

                There's nothing elegant about int n, it's wrong.

                You have
                m = (*n);
                where the type of (*n) is a long.

                There's no long object defined anywhere
                for the (*n) expression to refer to.
                You're casting an int address to a long address
                and dereferencing it. That's undefined.

                --
                pete

                Comment

                • Max

                  #9
                  Re: Function call problems (64-bit)

                  I am sorry, instead of "preview" I clicked on "send" and I could not
                  check the correctness.
                  This works:

                  retval = fun1(&n1, x);

                  Max

                  Comment

                  • Dik T. Winter

                    #10
                    Re: Function call problems (64-bit)

                    In article <43845374.4866@ mindspring.com> pfiland@mindspr ing.com writes:
                    ....[color=blue][color=green]
                    > > If I have a function (translated from fortran using f2c)[/color][/color]
                    ....[color=blue][color=green]
                    > > where (from f2c.h)
                    > >
                    > > typedef long int integer;
                    > > typedef double doublereal;[/color]
                    >
                    > I dislike reading code like that.[/color]

                    The code that f2c generates is not intended for human consumption.
                    --
                    dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
                    home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

                    Comment

                    • Christopher Benson-Manica

                      #11
                      Re: Function call problems (64-bit)

                      Max <iprmaster@gmai l.com> wrote:
                      [color=blue]
                      > int n = 5;
                      > integer n1 = n;[/color]
                      [color=blue]
                      > retval = fun1(n1, x);[/color]

                      Still not correct; fun1 expects an *address* as its first argument.
                      Presumably you intended

                      retval = fun1(&n1, x);

                      --
                      Christopher Benson-Manica | I *should* know what I'm talking about - if I
                      ataru(at)cybers pace.org | don't, I need to know. Flames welcome.

                      Comment

                      • Mike Wahler

                        #12
                        Re: Function call problems (64-bit)


                        "Dik T. Winter" <Dik.Winter@cwi .nl> wrote in message
                        news:IqErJD.Gz2 @cwi.nl...[color=blue]
                        > In article <43845374.4866@ mindspring.com> pfiland@mindspr ing.com writes:
                        > ...[color=green][color=darkred]
                        > > > If I have a function (translated from fortran using f2c)[/color][/color]
                        > ...[color=green][color=darkred]
                        > > > where (from f2c.h)
                        > > >
                        > > > typedef long int integer;
                        > > > typedef double doublereal;[/color]
                        > >
                        > > I dislike reading code like that.[/color]
                        >
                        > The code that f2c generates is not intended for human consumption.[/color]

                        Oh, so that's what that bad taste is. :-)

                        -Mike


                        Comment

                        • Barry Schwarz

                          #13
                          Re: Function call problems (64-bit)

                          On 23 Nov 2005 01:35:40 -0800, "Max" <iprmaster@gmai l.com> wrote:
                          [color=blue]
                          >Warning: newbie question!
                          >If I have a function (translated from fortran using f2c)
                          >
                          >int fun1(integer *n, doublereal *x)
                          >{
                          > integer m, i;
                          >
                          > m = (*n);
                          > for(i = 0; i < m; i++)
                          > x[i] = 0.;
                          >
                          > return 0;
                          >}
                          >
                          >where (from f2c.h)
                          >
                          >typedef long int integer;
                          >typedef double doublereal;
                          >
                          >
                          >Then I use it in a C program written from scratch:
                          >
                          >< all include files here>
                          >
                          >int main()
                          >{
                          > int n = 5;
                          > double *x = malloc(n * sizeof(doublere al));
                          > int retval;
                          >
                          > retval = fun1((integer &)n, x);[/color]

                          You cannot lie to the compiler and expect things to work. fun1
                          expects to receive a long*. You are giving it something that looks
                          like a long* but actually points to an int.

                          If this int is not aligned properly for a long you have invoked
                          undefined behavior. If your machine requires alignment, then a seg
                          fault is a desirable result.

                          If sizeof(int) != sizeof(long), the attempt to dereference the
                          address also invokes undefined behavior. As a practical matter, it
                          will probably result in a value wildly different than 5L. This would
                          most likely cause the array index to go way out of bounds and again a
                          seg fault is a desirable result.
                          [color=blue]
                          >
                          > return 0;
                          >}
                          >
                          >
                          >I get segmentation fault on 64-bit architecture. The problem is that n
                          >is not passed correctely to fun1, even with a cast. Defining in main()
                          >
                          >integer n = 5
                          >
                          >then it works. A more elegant solution?[/color]

                          How much more elegant can a solution be? This is cheap (almost free),
                          simple, effective, portable, efficient, correct, etc. Maybe you are
                          looking for something like "rewrite the f2c program so it produces
                          decent code"?


                          <<Remove the del for email>>

                          Comment

                          Working...