3

我在两台机器上本地编译了完全相同的源代码/make 文件:Linux Fedora 16 32 位和 Linux Fedora 17 64 位。

在 32 位机器上:

(gdb) break FRS::FRS
Breakpoint 4 at 0x804ea29: file ntfs.cpp, line 751.
Breakpoint 5 at 0x804e18f: file ntfs.cpp, line 505.
warning: Multiple breakpoints were set.
Use the "delete" command to delete unwanted breakpoints.

GNU gdb (GDB) Fedora (7.3.50.20110722-16.fc16)

在 64 位机器上:

(gdb) break FRS::FRS
Breakpoint 1 at 0x407daf: file ntfs.cpp, line 751.

GNU gdb (GDB) Fedora (7.4.50.20120120-54.fc17)

使用 32 位调试会话中的知识,我设置了另一个断点(并删除了第一个断点)来调试正确的功能。但是,它的执行方式不同,并且对于同一个测试用例只命中了两次该构造函数。在 32 位环境中,它会遇到十几次断点。

FRS::FRS (MFT *Mft, uint32 MFTRef, bool shallow)   // this is line 505
{
        memset (this, 0, sizeof *this);
        ParentMFT = Mft;
        MFTReference = MFTRef;
        Volume  *vol = GetParentVolume ();

        frs_bytes = ParentMFT -> GetFRSSizeInBytes();
        frs_buf = new uint8 [frs_bytes];
        if (!frs_buf)
        {
                fprintf (stderr, "FRS: alloc(%u) err\n", frs_bytes);
                exit (1);
        }

        int     sects = ParentMFT->GetFRSSizeInSectors();       // sectors per FRS
        bool    rc;

        if (!MFTRef)
                rc = vol -> RelativeRead (frs_buf, ParentMFT->GetMFTStart(), sects);
        else
        {
                uint32 FirstLsn = Mft -> LogicalFromVirtual(MFTReference * sects);
                uint32 LastLsn  = Mft -> LogicalFromVirtual(MFTReference * sects + sects - 1);

                if (FirstLsn + sects - 1 == LastLsn)    // is contiguous?
                        rc = vol -> RelativeRead (frs_buf, FirstLsn, sects);    // optimize read
                else
                {       // not contiguous:  read sectors one at a time
                        for (int j = 0;  j < sects;  ++j)
                        {
          ... (170 more lines)


// copy constructor
FRS::FRS(FRS *frs)   // this is line 751
{
        int     j;
        *this = *frs;
        if (frs_buf)
        {
                frs_buf = new uint8 [frs_bytes];
                memcpy (frs_buf, frs -> frs_buf, frs_bytes);
        }

        DAttr = NULL;
        StreamList = NULL;
      ...  // 50 more lines

这个函数将被编译掉的 64 位代码有什么本质上的不同吗?(它是一个 204 行函数,所以我在证明它不平凡后将其截断。)

什么可以解释为什么gdb没有“看到”相同的构造函数集,以及为什么代码似乎没有被调用那么多——尽管为什么它与“全部或全部”不同是一个谜。

4

1 回答 1

2

您正在比较不同版本的 gdb 以及不同版本的 gcc。那只是太多变数了。

很可能是调试信息差异。但仅凭这些信息是不可能的。

要知道的一件事是 C++ ABI 指定要发出的构造函数的多个副本。有“负责”和不负责的变体。gdb 将在它找到的所有断点上放置断点。

但是,我认为这可能会受到 debuginfo 和其他因素的影响。从源代码到可执行文件所发生的情况并不总是很明显......如果您真的想确切地找到发生这种情况的原因,您可以使用“nm”和“readelf -wi”等工具来挖掘符号和调试信息。

于 2013-05-26T18:57:07.947 回答