我有一个充满图像的文件夹,其中包含一些元数据,这些元数据以我尝试用程序提取的像素为单位。程序循环遍历每个文件,提取数据。问题是某些图像已损坏,尝试从中提取数据会导致分割错误。
是否有任何方法可以捕获此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;
}
答案 0 :(得分:2)
可能值得研究的另一种解决方案:(假设您使用的是Linux或其他Unix变体)
在处理每个图像之前,将进程分为两个进程,一个父进程和一个子进程(否则将是相同的,请查看fork(2)的手册页)。让孩子做一些冒险的事情,当父母等待它终止时,它可能会崩溃。如果孩子崩溃了,父母可以检测到它并且仍然处于良好状态,因此可以继续到下一个图像。如果子级成功,则可能需要一种方法,可以通过使用管道发送数据将结果从子级传输到父级。通过在fork调用之前打开管道,两个进程可以使用同一管道进行连接。
正如已经建议的那样,修复崩溃可能是最好的解决方案,但是有时这是不可能的,而您必须获得“创意”。
答案 1 :(得分:1)
编辑:SIGSEGV不能通过try-catch块作为异常捕获。
此页面:Catch SIGSEV解决了这个问题。
答案 2 :(得分:0)
您绝对不应“忽略SIGSEGV并继续执行”。
如果您的程序每次意外都写入某个未知的内存地址,则结果不确定。如果您的硬件检测到对不允许的内存区域的访问,那么您很幸运!最坏的情况是您访问内存时没有出现段错误。但是访问之后,您的内存已损坏。因此,您不能依赖您的代码和执行。
我相信您唯一能做的就是:编写正确的代码!这意味着:检查边界访问权限,也许只是使用STL中的容器并使用std::vector::at
之类的检查访问权限即可。
因为程序段不能保证结果,所以接受程序可以写入每个内存位置并不是解决方案。