GDAL常见的一些问题

1 在使用地面控制点进行几何纠正的时候,弹出来0x00007FFF2CBAEBB4 (gdal302.dll) (SURFMatch.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。

问题:无法进行纠正
原因:自己查找了原因,发现是因为没有设置地面控制点的id导致的,设置id之后正常运行

gcplist[i].pszId = id;

2 c++运行gdal出现ERROR 1: PROJ: proj_create_from_database: cannot find proj.db

思路就是:
找不到这个文件,那就让它找到,3种方式:
1是添加环境变量,然后重启电脑
2是在代码中指定路径;
3是放到exe下面;
有时候需要这3种中的两种方式都设置了。

参考了一些文档,发现主要有两个解决方法:
用第二种方法成功解决了这个问题:
一是添加环境变量
二是直接在代码中配置到proj.db的路径。

std::string path = "C:\\Program Files\\PROJ\\share\\proj";//proj.db所在文件夹
const char* proj_path[] = {
    
    path.c_str(), nullptr};
OSRSetPROJSearchPaths(proj_path);

C++版本GDAL3.5无法找到proj.db文件_c++ db文件_Linlp93的博客-CSDN博客

关于GDAL运行时出现Cannot find proj.db的解决办法_阿酷亚莫塔塔(张学鹏)的博客-CSDN博客

3 使用c++的gdal和omp加上读取数据时,报错ERROR 1:GetBlockRef failed at X block offect 0, Y block offect 12210。Segmentation fault (core dumped)。这是两个不同的错误。

GetBlockRef failed at X block offect 0, Y block offect 12210。是gdal读数据的错误。
Segmentation fault (core dumped)。是内存不足的错误

1、可能原因
自己在windows上运行代码正常,然后放到linux上运行,报这个错误。
无非就是下面4种原因:
(1)、omp资源冲突;自己在windows上正常运行,基本排除这个错误。
(2)、读取的数据错误;自己为了验证,关闭omp加速,发现正常运行,可以正常读取数据,说明一定是omp的原因。
(3)、依赖库的原因;自己之前有一个omp代码可以正常运行,这次也不能运行了,也没有排除这个错误。
(4)、内存资源不够的原因;自己的omp发现同时起了好多线程,在shell脚本中加了export OMP_NUM_THREADS=4。发现并没有起作用。之后又在代码中加了下面的话发现程序正常执行了,这里限制线程数为4个,而不是很多个,这样程序占用的内存少了:

#include <omp.h>

int main() {
    
    
    omp_set_num_threads(4);
    // 并行读取的代码
    // ...
    return 0;
}

2、原因:
内存资源不足导致这个问题。

3、解决方式1:在程序中限制omp的线程数量
在程序中加上上面的代码,程序正常运行了

#include <omp.h>

int main() {
    
    
    omp_set_num_threads(4);
    // 并行读取的代码
    // ...
    return 0;
}

解决方式2:清空系统内存
使用下面命令,清除系统里面的缓存,提供更多内存:

sudo sync && sudo echo 3 > /proc/sys/vm/drop_caches

4 Segmentation fault (core dumped)内存不足

Segmentation fault (core dumped)多为内存不当操作造成。空指针、野指针的读写操作,数组越界访问,破坏常量等。对每个指针声明后进行初始化为NULL是避免这个问题的好办法。

一个快速解决的方法是看系统内存,free -h,看free字段剩多少G内存。

内存不足的话,需要清理内存:

sudo sync && sudo echo 3 > /proc/sys/vm/drop_caches

5 同时报4个错误GetBlockRef failed at X block offect 0, Y block offect 4373,

ERROR1: GF2-035009809.tif,band 2: IReadBlock failed at X offset 0, Y offset 4373,
ERROR1:GetBlockRef failed at X block offect 0, Y block offect 4373,
ERROR1:TIFFFillStrip:Read error at scanline 2; get 0 bytes, expected 18438,
ERROR1:RIFFReadEncodedStrip() failed.

1 问题:
使用GDAL读取数据时启用omp出现这个错误,omp启用线程为1,不报任何错误。omp启用线程为2,报错了两次,有时候不报这个错误。但是当omp启用线程为8时,报了1000多次这个错误。

线程数越多,报上面错误次数越多,最多的时候可以超过几千次。也就是获取不到数据。

2 原因:
排除:
(1)排除影像大小的原因:mss.tif和dom.tif都会报错,mss.tif切块是10001000大小会报错,dom.tif切块30003000会报错,但是dom.tif报错的次数更多。如果将dom.tif设置为1400*1400大小也会报上面错误。
(2)排除数据问题,数据是正确的,因为单线程访问正常。

发现原因:

就是gdal访问资源冲突了,gdal多线程读取同一位置影像块会冲突,就是读取某一个像素的的时候只能有1个线程在读。

这些错误可能是由于并行处理导致的内存访问冲突或资源竞争引起的。当您增加线程数时,多个线程可能会同时访问相同的内存位置或资源,导致读取错误或失败。
为了解决这个问题,您可以尝试以下几点:
确保在并行处理期间,每个线程都在不同的内存位置上进行操作,以避免冲突。可以使用OpenMP的private和shared指令来控制变量的私有和共享访问。
尝试减少并行处理的线程数,以降低资源竞争的可能性。您可以逐步减少线程数,直到不再出现错误。
检查代码中是否存在其他可能导致冲突的部分。例如,如果有其他共享资源或全局变量,可能需要使用互斥锁或其他同步机制来保护它们。
确保您的代码在并行处理期间正确释放和管理内存,以避免内存泄漏或访问已释放内存的错误。
如果可能的话,尝试使用调试工具来跟踪错误发生的位置,并查看是否有任何明显的冲突或错误。
请注意,并行处理可能会增加代码的复杂性和调试难度。因此,在使用并行处理时,确保您的代码正确地处理并发访问和资源管理非常重要。

3 解决:
多个线程同时用gdal读取遥感数据块可能会导致冲突和不正确的结果。为了避免这种情况,我们可以使用OpenMP的critical指令来保护对共享资源的访问。
用#pragma omp critical {}把读取像素的代码包起来,注意{}必须另起一行,不能和#pragma omp critical在同一行

std::vector<cv::Mat> imgMat;     // 每个波段
int size = xpixel * ypixel;      // 这里必须是int
float* pafScan = new float[abs(size)];   // 存储数据,这句读取大影像直接报错了
if (pafScan == NULL) {
    
    
	std::cerr << "pafScan Failed to allocate memory." << std::endl;
	cv::Mat img_null;
	return img_null;
}
#pragma omp critical 
{
    
    
	for (int i = 0; i < band_number; i++) {
    
    
	int band = bands[i];
	GDALRasterBand* pBand = poDataset->GetRasterBand(band);
	// 读取栅格数据,并将其存储在pafScan中
	pBand->RasterIO(GF_Read, left, top, xpixel, ypixel, pafScan,
		xpixel, ypixel, St.iDataType, 0, 0);
	// 这里创建的时候是行数、列数
	cv::Mat tmpMat = cv::Mat(ypixel, xpixel, MdataType, pafScan);
	imgMat.push_back(tmpMat.clone());  // n个波段放到imgMat数组中去
	tmpMat.release();
	}
}

//释放内存
delete[]pafScan;
pafScan = NULL;
cv::Mat img;
img.create(St.Ysize, St.Xsize, MdataTypes);
// 将多通道数组转换为图像数组
cv::merge(imgMat, img);

5 无法找到.dll库

解决方式:
将.dll动态链接库放到可执行文件.exe可以找到的位置
在这里插入图片描述

6 无法定位程序输入点

无法定位程序输入点 solite3 column origin name 于动态链接库D: XiaoMaCode\CPlusPlusCode Third party library GDAL322\bingdal302dll
在这里插入图片描述

2.2 原因

很可能是因为.dll库不能用,或者调库混乱。

2.3 解决方案

开始将.dll库放到了系统变量中,出现问题。
将.dll文件放到了exe的同级目录,可以正常执行。

猜你喜欢

转载自blog.csdn.net/xiaotiig/article/details/129703348