忽略SIGSEGV并继续执行

时间:2018-11-07 09:24:56

标签: c++

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

是否有任何方法可以捕获此SIGSEGV信号,并使用它忽略当前损坏的图像并继续下一个操作?

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;

}

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:1)

编辑:SIGSEGV不能通过try-catch块作为异常捕获。

此页面:Catch SIGSEV解决了这个问题。

答案 2 :(得分:0)

您绝对不应“忽略SIGSEGV并继续执行”。

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

我相信您唯一能做的就是:编写正确的代码!这意味着:检查边界访问权限,也许只是使用STL中的容器并使用std::vector::at之类的检查访问权限即可。

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