C 结构、指针和铸造型芯转储
我有一个30年前编写的C程序(用于ISAM文件),其中有一个部分可以帮助我理解/修复。写这篇文章的人看到他/她的评论可能会有未来的问题。它编译的很好,但是核心转储 以下是问题所在:C 结构、指针和铸造型芯转储,c,pointers,data-structures,casting,C,Pointers,Data Structures,Casting,我有一个30年前编写的C程序(用于ISAM文件),其中有一个部分可以帮助我理解/修复。写这篇文章的人看到他/她的评论可能会有未来的问题。它编译的很好,但是核心转储 以下是问题所在: altkptr = (struct keydat *)(++header); 功能代码: struct indxheader { int pnumrecs ; long pnxtposn ; int pnextnode ; long pfreedat
altkptr = (struct keydat *)(++header);
功能代码:
struct indxheader {
int pnumrecs ;
long pnxtposn ;
int pnextnode ;
long pfreedat ;
int pfreenodes;
#ifdef FIXED_RECLEN
int preclength; /* Added 23-Jun-89 .. kavi */
#endif
int paltkeys ;
};
struct keydat {
int pkeylength,
proot,
pmaxkeys,
pnodesize,
pnumkeys,
pkeyparts ,
*partsarray ;
};
static int buildtables(alloc_flg)
int alloc_flg ; /* if occupy slot etc are to be called */
{
struct indxheader *header ;
struct keydat *altkptr;
int savekey, i ;
int *sptr, *dptr ;
savekey = currkeyno ;
if(seek(0) == ERROR)
reterr(NODSKERR);
if(read(currslot.fd2,ptr2,INXHSZ)<INXHSZ)
reterr(IFLRDERR); /* SIZE OF HEADER BLOCK IN FILE < SIZE DECLARED IN ISNAMES.H */
header = (struct indxheader *)ptr2 ;
currslot.numrecords = header->pnumrecs ; /*added .. if i have luck*/
#ifdef FIXED_RECLEN
currslot.reclength = header->preclength ;
#endif
currslot.nxtposn = header->pnxtposn;
currslot.nextnode = header->pnextnode;
currslot.freedat = header->pfreedat;
currslot.freenodes = header->pfreenodes;
currslot.altkeys = header->paltkeys;
/** If occupyslot to be called then check **/
if ( alloc_flg )
if (alloctable() == ERROR) return (ERROR) ;
altkptr = (struct keydat *)(++header); /* deserves attention..*/
for(currkeyno = 0;currkeyno<currslot.altkeys;currkeyno++) {
currindex.proot = altkptr->proot;
if (currindex.proot == -1) reterr (CRPIXFLERR) ;
currindex.pmaxkeys = altkptr->pmaxkeys;
currindex.pnodesize = altkptr->pnodesize;
currindex.pnumkeys = altkptr->pnumkeys;
currindex.pkeyparts = altkptr->pkeyparts ;
currindex.pkeylength = altkptr->pkeylength ;
altkptr++ ;
sptr = (int *)altkptr ;
if (alloc_flg) {
if ((currindex.partsarray = dptr = (int *)malloc((unsigned)(currindex.pkeyparts*4)*sizeof(int))) == NULL) reterr(MEMORYERR) ;
for (i = 0 ; i<(currindex.pkeyparts*4) ; i++)
*dptr++ = *sptr++ ;
}
else sptr += (currindex.pkeyparts*4) ;
altkptr = (struct keydat *)sptr ;
}
currkeyno = savekey ; /*restore currkeyno to its initial value*/
return (NOERROR);
}
struct indxheader{
国际pnumrecs;
长pnxtposn;
int-pnextnode;
长pfreedat;
内螺纹;
#ifdef已修复
int preclength;/*于1989年6月23日添加。.kavi*/
#恩迪夫
int paltkeys;
};
结构键数据{
int pkeylength,
普罗特,
pmaxkeys,
pnodesize,
pnumkey,
pkeyparts,
*帕萨雷;
};
静态int构建表(alloc_flg)
int alloc_flg;/*如果要调用占用插槽等*/
{
结构indxheader*头;
结构keydat*altkptr;
int savekey,i;
int*sptr,*dptr;
savekey=currkeyno;
如果(搜索(0)=错误)
reterr(NODSKERR);
如果(读(currslot.fd2,ptr2,INXHSZ)pnumrecs;/*添加..如果我运气好的话*/
#ifdef已修复
currslot.reclength=收割台->长度;
#恩迪夫
currslot.nxtposn=标题->pnxtposn;
currslot.nextnode=标题->pnextnode;
currslot.freedat=标题->pfreedat;
currslot.freenodes=标题->绿色节点;
currslot.altkeys=页眉->页面键;
/**如果要调用占用插槽,请检查**/
如果(alloc_flg)
if(alloctable()==ERROR)返回(ERROR);
altkptr=(struct keydat*)(++header);/*值得注意*/
for(currkeyno=0;currkeynoproot;
if(currenindex.proot==-1)reterr(crpixfler);
currenindex.pmaxkeys=altkptr->pmaxkeys;
currendex.pnodesize=altkptr->pnodesize;
currenindex.pnumkeys=altkptr->pnumkeys;
currenindex.pkeyparts=altkptr->pkeyparts;
currenindex.pkeylength=altkptr->pkeylength;
altkptr++;
sptr=(int*)altkptr;
如果(alloc_flg){
如果((currendex.partsarray=dptr=(int*)malloc((未签名)(currendex.pkeyparts*4)*sizeof(int))==NULL)reterr(MEMORYERR);
for(i=0;i标题
是指向struct indxheader
它被转换为altkptr
,这是一个struct-keydat
这是:
altkptr = (struct keydat *)(++header);
这相当于:
++header;
altkptr = (struct keydat *) header;
早在1989年,演员阵容是否有效可能是一个争论点。但是
标题的增量是问题所在
1989年,long
具有与int
相同的sizeof
[因此在struct
]中对齐]。这是因为大多数/所有CPU都是32位(或16位)
现在,您可能在64位机器上。因此,long
是64位
因此,在1989年,每个结构的大小[可能]匹配。现在,大小[可能]不同
因此,标题
的增量无效
您可能会幸运地使用-m32
进行强制32位模式编译。但是,这段代码太不稳定了,否则我建议您将其用作[松散的]指南,并尽可能重写
更新:
我从1981年开始编写C代码,所以我对当时可用的系统有些熟悉
其中一个问题是,keydat
struct有一个嵌入式指针,该指针存储在ISAM文件中并从ISAM文件中读取
如果是这样,取消引用这样的回读指针几乎肯定会导致错误或产生错误的结果
这是因为无法保证程序已加载到内存中的相同位置
一个关键问题是,您是否正在尝试移植此代码,以便可以读取很久以前创建的现有旧ISAM文件。如果不是,最好使用现有代码作为指南,从头开始重写
如果您确实需要读取旧文件,那么准确了解软件运行的系统类型会有所帮助
如果它在那个时代的电脑上运行,在MS/DOS下,int
可能是16位,long
是32位
如果它是在摩托罗拉的mc68000 Unix系统上运行的(例如旧的Sun Microsystems)[我在一家设计和制造类似系统的初创公司],那么长的是32位,但是int
可以是16位或32位。大多数系统对int
使用32位,但这是编译器的选择
此外,PC机是小端机,但mc68000
Unix系统是大端机
因此,首先,您必须确定int
的sizeof
、long
,以及era系统的指针
此外,还需要确定使用了什么样的结构成员对齐方式
然后,您可能必须重写读入该数据的函数,几乎是逐字节的,并在每个字段的基础上进行转换,以获得正确的字段读取字节数及其endianness
这与XDR
必须执行的操作类似。当它进行CoreDump时,错误消息是什么?使用您最喜欢的调试器检查core dump,它会告诉您更多信息。但我看不出altkptr=(struct keydat*)(++header)是如何执行的
可能会导致问题,因为这是一个简单的指针赋值。听起来不错,但为什么它会在赋值时崩溃呢?没有任何解引用,增加头本身也没有错。但是从一个结构到另一个结构的转换看起来很可疑。@Jabberwocky我们可能必须阅读好的print…[在OP的问题中]。他说这是“问题线”。这是一个很好的观点,但这并不是说分段故障发生在那里。正如你所说的,它不能分段故障,因为它只是一个增量,而不是一个deref。所以,我对这一点的看法是OP[如他所述]是基于这一行上的评论。分段故障可能会在稍后发生。谢谢。那就是