Thread: malloc problem in SUN in 64-bit compilation

  1. #1
    Registered User
    Join Date
    Apr 2003
    Posts
    18

    Unhappy malloc problem in SUN in 64-bit compilation

    Hi, I have a fortran77 program calling a C program to do memory allocation, and it compiled and ran fine under SUN's 32-bit environment. But when I compiled and ran under 64-bit, the code
    has run-time error:

    The actuall code crashed at:

    loop = 1
    signal SEGV (no mapping at the fault address) in mm_new_ad at line 991 in file "mm2000.f"
    991 link(j) = j + 1

    And link is pointed to by lptr, defined in mm2000.h, a header file for mm2000.f
    </bigscr/TEMP> grep -n link mm2000.h
    49: pointer (lptr, link)
    50: integer link(*)

    lptr is the return pointer from mallocf (called a few lines before the error line within mm2000.f -- a Fortran77 code):

    lptr = mallocf (max_ad*BYTES_PER_INT)

    The definition of mallocf is:
    Code:
    ________________________________________________
    long int mallocf_(nwords)
        long int *nwords;
    {
    
        long int iptout;
        long int nbytes;
    
        nbytes = (*nwords);
        if(!(iptout= malloc(nbytes))) {
             printf("MALLOCF: Out of memory.\n");
             exit(1);
        }
                   
        return iptout;
    
    }
    ________________________________________________
    I learned that c malloc returns a void pointer to the first byte of the address just allocated, so when this return pointer is then assigned to an long integer (iptout), this would mean that the actual address-of-the-first-byte is given to iptout, and then passed back to lptr. So now I test whether there is a problem here:

    I tested all 3 pointers defined slightly ahead of line 991 (error):

    adnptr = mallocf (max_ad*2*BYTES_PER_CHAR)
    adaptr = mallocf (max_ad*AD_SIZE*BYTES_PER_PTR)
    lptr = mallocf (max_ad*BYTES_PER_INT)

    **********************************************
    adnptr = 0 (before calling mallocf)
    Within mallocf:
    10 if(!(iptout= malloc(nbytes))) {
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) p iptout
    iptout = 4295023136
    adnptr = 1224288L (after calling mallocf)

    **********************************************
    adaptr=0 (before)
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) p iptout
    iptout = 1224288
    adaptr = 1256304LL (after)

    **********************************************
    lptr=0 (before)
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) p iptout
    iptout = 1280320
    lptr = 1280320LL (after)

    adnptr and adaptr seem not to be correct, though
    lptr seems to get the correct value/address from mallocf, but
    the program still crashed right afterwards:

    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) s
    stopped in mm_new_ad at line 990 in file "mm2000.f"
    990 do j = max_ad_orig + 1, max_ad - 1
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) s
    stopped in mm_new_ad at line 991 in file "mm2000.f"
    991 link(j) = j + 1
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) s
    signal SEGV (no mapping at the fault address) in mm_new_ad at line 991 in
    file "mm2000.f"
    991 link(j) = j + 1
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) p max_ad_orig + 1, max_ad-1
    max_ad_orig+1 = 1LL
    max_ad-1 = 499LL
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) p link(1)
    dbx: cannot access address 0x138940
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) p &link(1)
    &(link)(1) = 0x138940

    I think the problem occurred when passing back the long int iptout (8 bytes under 64-bit compilation in SUN) which is given to Fortran's integer pointers (which will be 8 bytes too under 64-bit compilation), but then I'm not totally sure though... Can anyone explain a little bit about these return pointer values (iptout, lptr, etc)? Do they represent actual addresses in memory? Are my results above indicate that it's the error in passing pointer values between Fortran and C?

    Thanks!

  2. #2
    Registered User
    Join Date
    Apr 2003
    Posts
    18
    No -- there are neither prototypes for malloc(), nor for mallocf_() in either the module which contains mallocf_() or in the module (mm2000.f) which calls mallocf_(). I actually considered this a possibility that long integer return value gets truncated since mallocf_() is NOT prototyped any where. However, I don't know how to prototype a C function from a calling function that is Fortran77. Within mm2000.f, however, mallocf_() is declared external with an integer return type (which will be 8 bytes as I set the flag for the f90 compiler so that all integer are 8 bytes).

    integer mallocf
    external mallocf

    However, may be it's not sufficient to do just this. Some sort of prototyping is needed in addition. Please help!

  3. #3
    Registered User
    Join Date
    Apr 2003
    Posts
    18
    After I included stdlib.h in the module defining mallocf_(), and compile, I got:

    cc -g -xarch=v9a mmsc.c -c
    "mmsc.c", line 11: warning: improper pointer/integer combination: op "="

    I'm tempted to modify the code containing mallocf_, but it was written a long time ago by someone else for a big project. And it compiled and ran well under 32-bit and 64-bit on every other platforms other than SUN. So, I'm kind of hesitant to make much change in the source code.

    Code:
    long int mallocf_(nwords)
        long int *nwords;
    {
    
        long int iptout;
        long int nbytes;
    
        nbytes = (*nwords);
        if(!(iptout= malloc(nbytes))) {
             printf("MALLOCF: Out of memory.\n");
             exit(1);
        }
    
        return iptout;
    
    }
    Since after I included the stdlib.h, cc regonize that malloc return void pointer is given to a long int without any casting. Shall I use
    iptout=(int)malloc(nbytes) to cast this void pointer, and will this assign the address of the first byte allocated to this integer iptout??

    And how about prototyping mallocf_() from within the calling function (mm2000.f)? Can I put a line like

    long int mallocf_(nwords);

    within the header file of mm2000.h? However, the fortran code will be compiled by f77, which probably does not compile such a line well.

  4. #4
    Registered User
    Join Date
    Apr 2003
    Posts
    18
    I type casted the malloc as well as included <stdlib.h>, but the code crashed in the same place:

    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) p iptout
    iptout = 4295023136
    (/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) p adnptr
    adnptr = 1224288LL

    And adnptr is still not seemingly right after calling malloc_f()... Then it must be the fact that mallocf_() is not properly prototyped. Or maybe it's not accepting this old-style declaration of function argument:

    Code:
    long int mallocf_(nwords)
        long int *nwords;
    {...}
    Maybe I should use:
    Code:
    long int mallocf_(long int *nwords)
    {...}

  5. #5
    Registered User
    Join Date
    Apr 2003
    Posts
    18
    This is my question too! However, these C codes were specifically written (by a C expert I suppose) to allocate memory
    for a collection of Fortran77 codes. And I have no idea of the intention of this programmer why he/she used integer instead of using a pointer to receive the return address of malloc, nor am I sure maybe it's not a feature of Fortran/C interoperability that I should KEEP. Now I'm just writing test programs to see what WILL actaully work while exploring Fortran/C interoperability. Since I can't rewrite the a few hundrds of MB of source codes (written mostly in Fortran77), I have to find a way that will make it work with the existing codes setup, and rewrite these C codes maybe for Sun 64-bit platform...

    Thanks!

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    18
    Yes, I wrote a test fortran77 code which calls mallocf, here are both codes and a makefile:

    Code:
    </bigscr/TEMP/temp_FC> cat testProgram.f
            program test
            integer MAX,BYTES_PER_INT
            parameter(MAX=5,BYTES_PER_INT=8)
            pointer(lptr,link)
            integer link(*)
            integer i,j
    
            integer mallocf
            external mallocf
    
            lptr=mallocf(MAX*BYTES_PER_INT)
    
            do i=1,MAX
            link(i)=i+1
            end do
    
            do i=1,MAX
                    write(*,*) 'i= ',i,'link(i)= ', link(i)
            end do
            stop
            end
    Code:
     (some minor modification from the original)
    </bigscr/TEMP/temp_FC> cat mmsc.c
    #include<stdlib.h>
    long int mallocf(long int *nwords);
     
    long int mallocf_(long int *nwords)
    {
        long int iptout;
        long int nbytes;
        long int *p;
     
        nbytes = (*nwords);
    
        if(!(p= (long int *)malloc(nbytes))) {
             printf("MALLOCF: Out of memory.\n");
             exit(1);
        }
     
        iptout=(int)p;
        return iptout;
    }
    Code:
    </bigscr/TEMP/temp_FC> cat makefile (written for SUN 64-bit)
    FCompiler=f90
    FLinker=f90
    FCflags= -g -xarch=v9a -xtypemap=integer:64
    FLflags= -g -xarch=v9a -xtypemap=integer:64 
    
    CCompiler=cc
    CCflags=-g -xarch=v9a
    Objects=testProgram.o mmsc.o
    Program=testProgram
    
    $(Program): $(Objects)
            $(FLinker) $(FLflags) -o $@ $(Objects)
    
    testProgram.o: testProgram.f
            $(FCompiler) $(FCflags) -c $@ testProgram.f
    
    mmsc.o: mmsc.c
            $(CCompiler) $(CCflags) -c $@ mmsc.c
    
    clean:
            rm -f $(Objects)
    The current code still crashed at the first time link() is assigned a value.

    However, I'm not a computer scientist (never looked at assembly codes before, but might try to figure out). The same flag is used for fotran f90 compiler for 64 bit. Using the 64-bit flag, the size of long,long int, long int * and void * are 8 bytes, doubling the 32-bit eqivalents.

    </bigscr/TEMP> cc -xarch=v9a foo.c -o foo
    </bigscr/TEMP> ./foo
    char is 1 bytes
    short is 2 bytes
    int is 4 bytes
    long is 8 bytes
    long int is 8 bytes
    long long is 8 bytes
    long int * is 8 bytes
    void pointer is 8 bytes

    </bigscr/TEMP> cc foo.c -o foo
    </bigscr/TEMP> ./foo
    char is 1 bytes
    short is 2 bytes
    int is 4 bytes
    long is 4 bytes
    long int is 4 bytes
    long long is 8 bytes
    long int * is 4 bytes
    void pointer is 4 bytes

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    18
    Ohh-- it's a typo-- Yes, it should be

    iptout=(long int)p;

    Thank you!! The program now gave me correct result!!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bit fields problem
    By johndirect in forum C Programming
    Replies: 2
    Last Post: 10-21-2008, 11:15 AM
  2. Should I switch to Vista 64 bit?
    By skaldicpoet9 in forum Tech Board
    Replies: 12
    Last Post: 05-23-2008, 08:23 AM
  3. Formatting 64 bit integers
    By Dino in forum C++ Programming
    Replies: 6
    Last Post: 02-05-2008, 08:24 PM
  4. 64 bit testing
    By DrSnuggles in forum C++ Programming
    Replies: 7
    Last Post: 11-20-2007, 03:20 AM
  5. Compilation problem
    By Skarr in forum Linux Programming
    Replies: 3
    Last Post: 09-27-2002, 12:37 PM