[ncl-talk] Hidden length argument for fortran strings is 8 bytes with 64-bit ifort

Martin Otte martinjotte at gmail.com
Mon Apr 9 21:25:50 MDT 2018


Hello,

Compiling NCL_NCARG 6.4 on OSX with Intel ifort resulted in random crashes for me. Debugging the code, I saw that ncl was crashing where C code was accessing fortran strings. As explained in this note by Intel:

 https://software.intel.com/en-us/articles/passing-character-string-in-intel-64-mixed-fortranc-project <https://software.intel.com/en-us/articles/passing-character-string-in-intel-64-mixed-fortranc-project>

the hidden string length with Intel fortran is 8 bytes for x86_64 and 4 bytes for 32-bit code. In the NCL source code, size_t should therefore be used when passing string lengths between C and Fortran when using the Intel fortran compiler.

Gfortran always uses 4 byte integers for the string length, so the current NCL code works with gfortran.

So, for example, in ni/src/lib/hlu/Format.c, the code:

        NGCALLF(cpinrc,CPINRC)();

        {
                int len1,len2,len3,len4;
                NGstring cex1_f;
                NGstring cex2_f;
                NGstring cex3_f;
                NGstring cbuf_f;
                char *cbuf_c;
                len1 = NGSTRLEN(cex1);
                len2 = NGSTRLEN(cex2);
                len3 = NGSTRLEN(cex3);
                len4 = 128;
                cex1_f = NGCstrToFstr(cex1,len1);
                cex2_f = NGCstrToFstr(cex2,len2);
                cex3_f = NGCstrToFstr(cex3,len3);
                cbuf_f = NGCstrToFstr(cbuf,len4);
                NGCALLF(cpnumb,CPNUMB)(&value,&ndgd,&lmsd,&iexp,&lexp,
                               cex1_f,cex2_f,cex3_f,
                               &lex1[ix],&lex2[ix],&lex3[ix],
                               &ioma,&iodp,&iotz,cbuf_f,&nbuf,&ndgs,&ieva,
                               len1,len2,len3,len4);


should be

        NGCALLF(cpinrc,CPINRC)();

        {
                size_t len1,len2,len3,len4;
                NGstring cex1_f;
                NGstring cex2_f;
                NGstring cex3_f;
                NGstring cbuf_f;
                char *cbuf_c;
                len1 = NGSTRLEN(cex1);
                len2 = NGSTRLEN(cex2);
                len3 = NGSTRLEN(cex3);
                len4 = 128;
                cex1_f = NGCstrToFstr(cex1,len1);
                cex2_f = NGCstrToFstr(cex2,len2);
                cex3_f = NGCstrToFstr(cex3,len3);
                cbuf_f = NGCstrToFstr(cbuf,len4);
                NGCALLF(cpnumb,CPNUMB)(&value,&ndgd,&lmsd,&iexp,&lexp,
                               cex1_f,cex2_f,cex3_f,
                               &lex1[ix],&lex2[ix],&lex3[ix],
                               &ioma,&iodp,&iotz,cbuf_f,&nbuf,&ndgs,&ieva,
                               len1,len2,len3,len4);

for the Intel compiler. Changing some of these resulting in a working NCL for me.

Although passing the wrong size argument on OSX causes crashes, Linux seems more forgiving and the code doesn’t crash (although it’s still incorrect).

Maybe the type for fortran string sizes should be a preprocessing symbol that gets set before compilation to “size_t” or “int” depending on if one is using ifort or gfortran?

Thanks and I hope this is helpful,

Martin

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.ucar.edu/pipermail/ncl-talk/attachments/20180409/634d1bfe/attachment.html>


More information about the ncl-talk mailing list