【问题标题】:Structure, pointer and casting core dump结构、指针和铸造核心转储
【发布时间】:2020-05-08 15:23:13
【问题描述】:

我有一个 30 年前编写的 C 程序(用于 ISAM 文件),其中有一个部分可以帮助我理解/修复。写这篇文章的人看到他/她的 cmets 可能会出现未来的问题。它编译得很好,但核心转储。

这是问题所在:

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);
}

【问题讨论】:

  • 核心转储时,错误信息是什么?使用您最喜欢的调试器检查核心转储,它会告诉您更多信息。但我看不出altkptr = (struct keydat *)(++header) 是如何导致问题的,因为它是一个简单的指针分配。

标签: c pointers data-structures casting


【解决方案1】:

header 是指向struct indxheader 的指针

它被转换为altkptr,这是一个struct keydat

这是:

altkptr = (struct keydat *)(++header);

这相当于:

++header;
altkptr = (struct keydat *) header;

1989 年的选角是否有效可能是一个争论点。但是……

header 的增量是问题。

在 1989 年,longint 具有相同的 sizeof [因此在 struct 中对齐]。这是因为大多数/所有 CPU 都是 32 位(或 16 位)。

现在,您可能使用的是 64 位机器。所以,long 是 64 位。

因此,在 1989 年,每个 struct 的大小 [可能] 匹配。现在,尺寸 [可能] 不同

因此,header 的增量无效。

可能有幸使用-m32 进行强制 32 位模式编译。但是,这段代码太摇摇晃晃,否则我会说将其用作 [松散] 指南并尽可能重写。


更新:

我从 1981 年开始编写 C 代码,所以我对当时可用的系统有点熟悉。

其中一个问题是keydat 结构有一个嵌入的指针,该指针被存储到 ISAM 文件并从中读取。

如果是这样,取消引用这样的回读指针几乎肯定会出现段错误或产生不正确的结果。

那是因为不能保证程序已经在同一个地方加载到内存中。

一个关键问题是您是否尝试移植此代码,以便可以读取很久以前创建的现有旧 ISAM 文件。如果没有,最好以现有代码为指导,从头开始重写。

如果您确实必须读取旧文件,那么准确了解正在运行该软件的系统类型会有所帮助。

如果它在那个时代的 PC 上运行在 MS/DOS 下,int 可能是 16 位,long 是 32 位。

如果它在摩托罗拉mc68000 Unix 系统(例如旧的 Sun Microsystems)[我在一家设计和制造类似系统的初创公司] 上运行,long 是 32 位,但int可以是 16 位或 32 位。大多数系统使用 32 位来表示 int,但是,这是编译器的选择。

此外,PC 是/曾经是小端,但 mc68000 Unix 系统是大端。

所以,首先,您必须确定intlongsizeof,以及该时代系统的指针。

此外,您需要确定结构成员的对齐方式。

然后,您可能必须重写读取该数据的函数,几乎是逐个字节地读取数据,并在每个字段的基础上进行转换,以获得要为字段读取的正确字节数及其字节序。

这类似于XDR 必须做的事情。

【讨论】:

  • 听起来不错,但为什么会在作业中崩溃?没有任何取消引用,增加header 本身并没有错。但是从一个结构转换到另一个结构看起来很可疑..
  • @Jabberwocky 我们可能需要阅读细则... [在 OP 的问题中]。他说这是“问题线”。一个很好的观点,但这并没有说段错误发生在那里。正如你所说,它不能 段错误,因为它只是一个增量,而不是一个 deref。所以,我对此的看法是,OP [正如他所提到的] 是基于在线评论。段错误可能会在以后发生。
  • 谢谢。这是有道理的——欣赏它。附带说明,它是在旧的 NCR 3000 上运行的,该 NCR 3000 在 AT&T SVr4 上具有微通道架构。无论如何,我确实计划重写,只是通过基础来了解发生了什么。再次感谢您的宝贵时间。
猜你喜欢
  • 1970-01-01
  • 2016-09-07
  • 2013-05-06
  • 2020-04-06
  • 1970-01-01
  • 1970-01-01
  • 2018-01-05
  • 2019-04-10
  • 2020-08-04
相关资源
最近更新 更多