【问题标题】:Ignore SIGSEGV and continue execution [duplicate]忽略 SIGSEGV 并继续执行 [重复]
【发布时间】:2019-04-10 17:06:31
【问题描述】:

我有一个充满图像的文件夹,其中包含我试图用我的程序提取的像素中的一些元数据。程序循环遍历每个文件,提取数据。问题是某些图像已损坏,尝试从中提取数据会导致分割错误。

有什么方法可以捕捉到这个 SIGSEGV 信号并用它来忽略当前损坏的图像并继续下一个 noe?

try-catch 无济于事,因为这是一个信号,而不是例外。

int Status::ExtractImageMetaData(cv::Mat src_in, int Index)
{
    unsigned char *Image = (unsigned char *)(src_in.data);
    unsigned char *StructByte = (unsigned char*) &ImageMetaData[Index];

    uint32_t MetaOffset = (src_in.total() * src_in.elemSize()) - sizeof(ImageMetaData_t);


    for(unsigned int i = 0; i < sizeof(ImageMetaData_t); i++)
    {
        StructByte[i] = Image[i + MetaOffset]; // SEGMENTATION FAULT HERE!

    }
}





int main(int argc, char const *argv[])
{

   if (imagePath == NULL){
        imagePath = "/Pictures/metadataExtractionTest/sqlTest/";
    }


// Iterate over all files in the "imagePath"
    for (const auto & p : fs::directory_iterator(imagePath)){

        string FullImageDir = p.path();
        Mat Img = imread(FullImageDir.c_str());

        int MetaStatus = SystemStatus.ExtractImageMetaData(Img, 0);     


        printf("done\n");

    } 


    return 0;

}

【问题讨论】:

  • 你不应该抓住SIGSEGV。你应该防止它。如果您有超出范围的数组访问权限,请在访问之前检查数组大小。检查null
  • 尽管我必须第二次处理段错误的建议@Yksisarvinen:段错误可能是因为您盲目地接受文件中的数据而不检查它。正确审查数据的合理性、规范和实施限制将 (1) 可能允许您容忍一些文件损坏并仍然提取一些图像或元数据,以及 (2) 使您的程序更安全。如果您在第三方来源上运行它甚至分发它,最后一个更为重要:因为恶意制作的文件实际上可能会攻击您的计算机。
  • 好的,伙计们。在尝试从中提取元数据之前,请遵循您的建议并检查输入图像中的列和行。成功了
  • 总是很高兴找到“正确”的解决方案——即解决根本问题并得到正确理解的解决方案。

标签: c++


【解决方案1】:

已编辑:SIGSEGV 无法通过 try-catch 块被捕获为异常。

此页面:Catch SIGSEV 解决问题。

【讨论】:

  • SIGSEGV 不是一个例外,它是一个信号。 try/catch 无济于事。
  • 已经试过 try-catch 是的。没用
  • 公平点 - 自从我使用 Linux 以来已经有一段时间了。会考虑的。
【解决方案2】:

可能值得研究的替代解决方案:(假设您使用的是 Linux 或其他一些 Unix 变体)

在处理每个图像之前,将进程分成两个,一个父进程和一个子进程(否则它们将是相同的,请查看 fork(2) 的手册页)。让孩子做一些危险的事情,当父母等待它终止时可能会崩溃。如果孩子崩溃,父母可以检测到这一点并且仍然处于良好状态,因此可以继续下一张图像。如果孩子成功,您将需要一种将结果从孩子传输到父母的方法,也许是通过使用管道发送数据。通过在 fork 调用之前打开管道,两个进程可以使用同一个管道进行连接。

正如已经建议的那样,修复崩溃可能是最好的解决方案,但有时这是不可能的,您必须获得“创造性”。

【讨论】:

  • 这是一个非常糟糕的主意!如果您将“某处”写入内存,则段错误是幸运的结果。如果你错误的内存访问是去一个允许但不是有意的内存地址,那么一切都可能发生。事实上,代码被设计破坏了。 “风险”意味着“运行错误的代码”并接受“一切皆有可能”根本不是解决方案!
【解决方案3】:

您根本不应该“忽略 SIGSEGV 并继续执行”。

如果您的程序意外写入某个未知内存地址,则结果未定义。如果您的硬件检测到对不允许的内存区域的访问,那么您很幸运!糟糕的情况是您访问内存而没有出现段错误。但访问后,您的内存已损坏。所以你不能依赖你的代码和执行。

我相信你唯一能做的就是:编写正确的代码!这意味着:检查越界访问,也许只需使用 STL 中的容器并使用检查访问,如 std::vector::at

接受程序可以写入每个内存位置并不是解决方案,因为段错误不是保证结果。

【讨论】:

    猜你喜欢
    • 2019-03-11
    • 1970-01-01
    • 2013-03-17
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 2011-12-01
    相关资源
    最近更新 更多