【问题标题】:C++ segmentation fault when calling function from a new location从新位置调用函数时出现 C++ 分段错误
【发布时间】:2017-11-26 02:02:12
【问题描述】:

我遇到了一个问题,即从不同位置调用具有相同参数的相同函数时出现分段错误。我试图在该函数中编写其他东西,但不知道为什么会出现段错误。然后我将其缩小到 writeSector 函数,所以我删除了所有其他内容并试图弄清楚为什么这给了我一个段错误,但我仍然不知道为什么。下面是调用同一个函数,然后从另一个函数中调用它的示例:

test[0] = '0';
test[1] = '0';
test[2] = '1';
test[3] = '0';
test[4] = '0';
test[5] = '4';
test[6] = '0';
test[7] = '0';
test[8] = '5';
test[9] = '0';
test[10] = '0';
test[11] = '5';
test[12] = '0';
test[13] = '0';
test[14] = '6';
test[15] = '9';
test[16] = '9';
test[17] = '9';
disk->writeSector(0, test);
disk->writeSector(10, test);
disk->writeSector(10, test);
disk->writeSector(10, test);
disk->writeSector(10, test);
generateRootDir(10); //Seg fault here.

该函数实际上调用了相同的代码,如下所示:

void FileSystem::generateRootDir(int rootBlock)
{
    disk->writeSector(10, test);
}

writeSector函数如下所示。

void BlockDisk::writeSector(int address, char* block)
{
    if (address > blocks || address < 0)
    {
        std::cout << "[writeSector] ERROR: Sector " << address << " out  of bounds!" << std::endl;
    }
    std::fstream diskWrite;
    diskWrite.open(disk, std::ios::binary | std::ios::in | std::ios::out);
    if (diskWrite)
    {
        diskWrite.seekp(address*BLOCKSIZE, diskWrite.beg);  
        diskWrite.write(block, BLOCKSIZE);
        diskWrite.close();
    } else {
        printf("Error opening file to write\n");
        exit(-1);
    }
}

然后我尝试在 generateRootDir 函数调用上方的一行设置一个断点。这是给定的输出,对我来说一切正常,我不明白为什么这里有任何东西会导致分段错误。

Breakpoint 1, FileSystem::mount (this=0x55555576bc20) at FileSystem.cpp:55
55          disk->writeSector(10, test);
(gdb) s
BlockDisk::writeSector (this=0x55555576c0c0, address=10,
    block=0x55555576bc90 "001004005005006999") at BlockDisk.cpp:21
21          if (address > blocks || address < 0)
(gdb) s
25          std::fstream diskWrite;

然后 writeSector 函数的其余部分运行良好。然后调用generateRootDir:

FileSystem::mount (this=0x55555576bc20) at FileSystem.cpp:56
56          generateRootDir(10);
(gdb) s
FileSystem::generateRootDir (this=0x55555576bc20, rootBlock=10)
    at FileSystem.cpp:147
147         disk->writeSector(10, test);
(gdb) s
BlockDisk::writeSector (this=0x0, address=10,
    block=0x55555576bc90 "001004005005006999") at BlockDisk.cpp:21
21          if (address > blocks || address < 0)
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x0000555555556733 in BlockDisk::writeSector (this=0x0, address=10,
    block=0x55555576bc90 "001004005005006999") at BlockDisk.cpp:21
21          if (address > blocks || address < 0)
(gdb) s

这两个调用的 gdb 似乎相同,但一个给出了分段错误。对此的任何帮助将不胜感激。

【问题讨论】:

  • writeSector (this=0x0, -- 查看this的值。这对你来说是不是正确的,即一个虚假的对象?这就是为什么您应该发布minimal reproducible example,以便我们知道您的变量来自哪里以及它们是如何创建的,变量如disk
  • 尝试通过valgrind 运行您的代码。如果你踩到了你不应该踩到的内存,它会告诉你。
  • 我不明白为什么这里有任何东西会导致分段错误。 -- 访问一个空指针就好像它是一个有效的对象可以做到这一点,并且从输出你正在展示,这就是它的样子。
  • disk 为空。如果没有更多代码,我们无法告诉您原因。 minimal reproducible example,请。

标签: c++ linux segmentation-fault gdb


【解决方案1】:

如果此行成功:

disk->writeSector(10, test);

generateRootDir 中的同一行以disk == NULL 失败:

void FileSystem::generateRootDir(int rootBlock)
{
    disk->writeSector(10, test);
}

那么disk的值在第一个位置有效,在第二个位置无效。

这两个disks 很可能引用不同的变量(其中一个已正确初始化,而另一个未正确初始化)。

你可以在 GDB 中验证这个理论:print &amp;disk 会在generateRootDir 内外产生不同的结果。

【讨论】:

  • 是的,这就是问题所在。我应该在构造函数中对其进行初始化,但由于某种原因,它在行工作的函数中被重新声明和初始化。我确信这一切都是在构造函数中完成的,所以我什至没有在那里寻找问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-08
相关资源
最近更新 更多