问题与GRIB解析器有关(链接到GRIB文件https://github.com/Gifciak/GRIB),
当我执行代码时(尽管代码块或通过控制台在Linux上-with dts as (
select date'2018-01-01' + level - 1 dt
from dual
connect by level <= 7
)
select to_char ( dt, 'Day' ) day_name,
( dt - trunc ( dt + 1, 'iw' ) ) day_number
from dts
order by day_number;
DAY_NAME DAY_NUMBER
Sunday -1
Monday 0
Tuesday 1
Wednesday 2
Thursday 3
Friday 4
Saturday 5
),我遇到了错误,即分段错误,但并非总是如此。
例如,当我编译10次时,有8次会出现错误,而2次一切都可以正常工作,这将为我提供控制台输出和信息。
根据我的研究,问题g++ main.cpp -pedantic
所在,因为它可能正在尝试一个不再存在的复制迭代器。
有人可以解释为什么会发生吗? 为什么它不总是崩溃或成功?
std::copy
这是预期的结果,因为我已经从控制台复制了它
size: 4538 sec0: 8 sec1: 28 sec2: 178 sec3: 4320 end flag: 4 sum: 4538 ### Section IS ### magicFlag: 1196575042 size: 1191186874 edition: 1 ### Section PDS ### size: 28 tableVersion: 2 indentificatorOfCenter: 7 numProcessID: 81 gridIndentification: 37 flagForGDSorBMS: 128 indParamAndUnit: 33 indTypeOfLevelOrLayer: 100 levelOrLayer: 850 year: 15 month: 3 day: 10 hour: 0 minute: 0 forecastTimeUnit: 1 p1: 0 p2: 0 indTimeRange: 10 averageOrAccumulate: 0 missing: 0 century: 21 subcenterId: 0 decimalScale: 1
答案 0 :(得分:5)
首先,使用g++ main.cpp -pedantic
并不是很有用,因为您尚未启用任何警告。将-Wall -Wextra
添加到编译器标志中,同时也添加-g
,以便您对其进行调试。
使用-fsanitize=undefined
进行编译会显示由于在需要有效指针的地方使用空指针而导致的运行时错误:
/usr/include/c++/8/bits/stl_algobase.h:368:23: runtime error: null pointer passed as argument 2, which is declared to never be null
Segmentation fault (core dumped)
这意味着您的程序存在错误。
使用-D_GLIBCXX_DEBUG
进行编译会向std::vector
添加其他检查,这会告诉您问题所在:
/usr/include/c++/8/debug/safe_iterator.h:374:
Error: attempt to advance a past-the-end iterator 4 steps, which falls
outside its valid range.
Objects involved in the operation:
iterator @ 0x0x7fffb09ceb90 {
type = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<unsigned char const*, std::__cxx1998::vector<unsigned char, std::allocator<unsigned char> > >, std::__debug::vector<unsigned char, std::allocator<unsigned char> > > (constant iterator);
state = past-the-end;
references sequence with type 'std::__debug::vector<unsigned char, std::allocator<unsigned char> >' @ 0x0x7fffb09cf050
}
Aborted (core dumped)
您应该在调试器下运行程序,以查看此无效的迭代器增量发生在何处。在GDB中运行该程序,然后使用其up
命令向上移动堆栈,显示错误来自loadData
中的错误:
constexpr char MAGIC_START[4] = { 'G', 'R', 'I', 'B' };
constexpr char MAGIC_END[4] = { '7', '7', '7', '7' };
auto start = std::search(rawdata.cbegin(),
rawdata.cend(),
std::begin(MAGIC_START),
std::end(MAGIC_START));
auto end = std::search(rawdata.cbegin(),
rawdata.cend(),
std::begin(MAGIC_END),
std::end(MAGIC_END));
ByteVec data(start, end + sizeof(MAGIC_END));
^^^^^^^^^^^^^^^^^^^^^^^
请考虑当rawdata
不包含MAGIC_START
字符,但确实包含MAGIC_END
字符时会发生什么。 start
和end
会形成有效的迭代器范围吗?
请考虑当rawdata
不包含MAGIC_END
字符时会发生什么。 end + sizeof(MAGIC_END)
有效吗?
您不应假定对std::search
的两个调用均能正常工作。您应该通过测试start == rawdata.end()
或end == rawdata.end()
来添加一些错误检查。如果其中任何一个为真,则说明出现了问题(rawdata
字符串中可能输入错误)。
您还应该学习如何使用调试器,并了解编译器提供的用于检测错误的其他工具(例如,应使用GCC的-fsanitize=undefined
和-D_GLIBCXX_DEBUG
选项来帮助确认是否存在错误) ,并且应该使用GDB查找这些错误的发生位置。