f2c转换C代码调用s_wsfe时cilist成员异常致崩溃
f2c转换后C代码调用
s_wsfe时cilist成员异常的排查方案 问题场景
运行f2c转换后的C代码时,调用s_wsfe函数出现崩溃,原因是传入的cilist结构体中cifmt成员在函数内部变为null,但在调用前该成员是正常指向字符串的。
MainFile.C代码
static char fmt_4[] = "This is a very long string..."; static cilist io___94 = { 0, 6, 0, fmt_4, 0 }; printf("io___94.cierr: -%d-\n",io___94.cierr); printf("io___94.ciunit: -%d-\n",io___94.ciunit); printf("io___94.ciend: -%d-\n",io___94.ciend); printf("io___94.cifmt: -%s-\n",io___94.cifmt); printf("io___94.cirec: -%d-\n",io___94.cirec); printf("sizeof io___94.cierr: -%lu-\n",sizeof(io___94.cierr)); printf("sizeof io___94.ciunit: -%lu-\n",sizeof(io___94.ciunit)); printf("sizeof io___94.ciend: -%lu-\n",sizeof(io___94.ciend)); printf("sizeof io___94.cifmt: -%lu-\n",sizeof(io___94.cifmt)); printf("sizeof io___94.cirec: -%lu-\n",sizeof(io___94.cirec)); s_wsfe(&io___94);
MainFile打印输出
io___94.cierr: -0- io___94.ciunit: -6- io___94.ciend: -0- io___94.cifmt: -This is a very long string...- io___94.cirec: -0- sizeof io___94.cierr: -4- sizeof io___94.ciunit: -4- sizeof io___94.ciend: -4- sizeof io___94.cifmt: -8- sizeof io___94.cirec: -4-
libf2c中s_wsfe函数代码
int s_wsfe(cilist *a) /*start*/ #endif { int n; printf("a->cierr: -%ld-\n",a->cierr); printf("ciunit: -%d-\n",a->ciunit); printf("ciend: -%ld-\n",a->ciend); printf("a->cifmt: -%s-\n",a->cifmt); printf("cirec: -%d-\n",a->cirec); printf("sizeof a->cierr: -%lu-\n",sizeof(a->cierr)); printf("sizeof ciunit: -%lu-\n",sizeof(a->ciunit)); printf("sizeof ciend: -%lu-\n",sizeof(a->ciend)); printf("sizeof a->cifmt: -%lu-\n",sizeof(a->cifmt)); printf("sizeof cirec: -%lu-\n",sizeof(a->cirec)); if(!f__init) f_init(); f__reading=0; f__sequential=1; f__formatted=1; f__external=1; if(n=c_sfe(a)) return(n); f__elist=a; f__hiwater = f__cursor=f__recpos=0; f__nonl = 0; f__scale=0; f__fmtbuf=a->cifmt; f__cf=f__curunit->ufd; if(pars_f(f__fmtbuf)<0) err(a->cierr,100,"startio"); //Crash here f__putn= x_putc; f__doed= w_ed; f__doned= w_ned; f__doend=xw_end; f__dorevert=xw_rev; f__donewrec=x_wSL; fmt_bg(); f__cplus=0; f__cblank=f__curunit->ublnk; if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit)) err(a->cierr,errno,"write start"); return(0); }
s_wsfe打印输出
a->cierr: -25769803776- ciunit: -0- ciend: -4323035328- a->cifmt: -(null)- cirec: -1- sizeof a->cierr: -8- sizeof ciunit: -4- sizeof ciend: -8- sizeof a->cifmt: -8- sizeof cirec: -4-
cilist结构体定义(来自f2c.h)
/*external read, write*/ typedef struct { flag cierr; ftnint ciunit; flag ciend; char *cifmt; ftnint cirec; } cilist;
核心问题分析
从两次打印的sizeof结果可以明确:cilist结构体的内存布局在你的代码和libf2c库中不一致。你的代码中cierr和ciend是4字节,而libf2c中这两个成员是8字节,导致传递指针后,libf2c访问成员时偏移错误,a->cifmt实际指向了结构体内存中的无效位置,因此显示为null,其他成员的值也完全错乱。
排查方向
统一
flag和ftnint的typedef定义
检查你的代码和libf2c使用的f2c.h中,这两个类型的定义是否完全一致。比如flag可能在libf2c中被定义为long(8字节),但你的代码中是int(4字节),直接导致结构体成员的大小和偏移错位。统一编译架构
确认你的代码和libf2c库是否都是32位或64位编译,混合架构会导致指针、长整型的大小差异,破坏结构体布局。验证头文件一致性
确保MainFile.C包含的是和libf2c完全相同版本的f2c.h,没有自定义或修改过结构体定义,也没有包含其他冲突的头文件。检查结构体内存偏移
在MainFile中打印每个成员的地址,在s_wsfe中也打印对应成员的地址,对比偏移是否一致:// 在MainFile中添加 printf("&io___94.cierr: %p\n", &io___94.cierr); printf("&io___94.ciunit: %p\n", &io___94.ciunit); printf("&io___94.ciend: %p\n", &io___94.ciend); printf("&io___94.cifmt: %p\n", &io___94.cifmt); printf("&io___94.cirec: %p\n", &io___94.cirec); // 在s_wsfe中添加 printf("&a->cierr: %p\n", &a->cierr); printf("&a->ciunit: %p\n", &a->ciunit); printf("&a->ciend: %p\n", &a->ciend); printf("&a->cifmt: %p\n", &a->cifmt); printf("&a->cirec: %p\n", &a->cirec);如果偏移不同,必然是结构体定义不匹配导致的。
内容的提问来源于stack exchange,提问作者ez4nick
相关产品推荐
相关产品推荐

