std::getline()导致segmention fault的奇怪问题.

[复制链接]
查看11 | 回复6 | 2021-1-27 06:52:07 | 显示全部楼层 |阅读模式
首先说一下程序逻辑:
程序是提交到hadoop的streaming跑的c++程序.所以需要从stdin读取数据进行处理.而且每一次循环读入的数据都很大可能一行要达到5Mb左右的数据量.
现象是,
当处理少量数据时,程序可以正常结束,但是当处理大量数据时,hadoop报错,subprocessfaildwithcode:11
也就是程序收到signal11,最终程序会产生segmentionfault错误.
我加-g参数编译(gcc编译器),生成带符号的版本,等segfault后,gdb-c加载dump文件,然后看堆栈调用,显示全部都是类似如下形式:
0xXXXXXXXXin??()
看样子是调用到什么库里崩的.
然后我将程序逐行打log,发现是崩溃在getline这个c++的库函数调用里.非常不解是怎么回事,哪位高手能解答一下.
下面是程序的部分代码:
intmain(intargc,char**argv){
Json::Readerjson;
staticcshhandle;
cs_errcerr;
cerr=cs_open(CS_ARCH_X86,CS_MODE_32,&handle);
while(true){
std::stringline;
printf("begin...\n");
if(std::getline(std::cin,line)){
printf("parsingstring....\n");
size_tpos=line.find_last_of("\t");
printf("firstfinddone...\n");
if(pos!=std::string::npos&&line.find("file_content")!=std::string::npos){
Json::Valueoutput,json_data;
if(json.parse(line.substr(pos),json_data)){
pos=line.find_first_of("\t");
output["md5"]=line.substr(0,pos);
printf("jsonparseend...\n");
std::stringzip_buffer=base64_decode(json_data["file_content"].asString());
size_tfile_buf_len=0;
void*file_buf=(void*)unzip(zip_buffer.c_str(),zip_buffer.length(),(size_t*)&file_buf_len);
zip_buffer.clear();
printf("unzipend...\n");
if(file_buf_len>=sizeof(IMAGE_DOS_HEADER)){
//check"MZ"signature
printf("checkingMZheader...\n");
if(*(unsignedshortint*)(file_buf)==0x5a4d){
PIMAGE_DOS_HEADERdos_header=(PIMAGE_DOS_HEADER)file_buf;
//check"PE"signature
printf("checkingPEheader...\n");
if(file_buf_len>=(dos_header->e_lfanew+sizeof(IMAGE_NT_HEADERS32))&&*(unsignedint*)((char*)file_buf+dos_header->e_lfanew)==0x4550){
PIMAGE_NT_HEADERS32nt_header=(PIMAGE_NT_HEADERS32)((char*)file_buf+dos_header->e_lfanew);
printf("gettingsection...\n");
PIMAGE_SECTION_HEADERpsh=get_section_header(file_buf,file_buf_len,nt_header->OptionalHeader.AddressOfEntryPoint);
printf("bordercheck...\n");
if(psh&&file_buf_len>=psh->PointerToRawData+psh->SizeOfRawData){
cs_insn*insn;
unsignedintaddress=nt_header->OptionalHeader.AddressOfEntryPoint+nt_header->OptionalHeader.ImageBase;
size_tcount=cs_disasm(handle,\
(uint8_t*)((char*)file_buf+RVA2OFFSET(nt_header->OptionalHeader.AddressOfEntryPoint,psh)),\
psh->PointerToRawData+psh->SizeOfRawData,\
address,0,&insn);
for(size_ti=0;i
下面是崩溃时的log:
begin...
parsingstring....
firstfinddone...
jsonparseend...
unzipend...
checkingMZheader...
checkingPEheader...
gettingsection...
bordercheck...
318e619313393266d4036b42815b5646
freebuffer...
-------------------------------
begin...
parsingstring....
firstfinddone...
jsonparseend...
unzipend...
checkingMZheader...
checkingPEheader...
gettingsection...
bordercheck...
860582da12e4205474eb8a0fb49e556b
freebuffer...
-------------------------------
begin...
[1]+段错误nohupcat/data/sample.bin|./asm>log.log2>&1

分 -->
回复

使用道具 举报

千问 | 2021-1-27 06:52:07 | 显示全部楼层
进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’
使用命令
gdb运行程序名core或core.数字
进入gdb然后使用bt命令
可以查看进程意外退出前函数调用的堆栈,内容为从上到下列出对应从里层到外层的函数调用历史。
如果进程意外退出不产生core文件,参考“ulimit-ccore文件最大块大小”命令

回复

使用道具 举报

千问 | 2021-1-27 06:52:07 | 显示全部楼层
怀疑不是由cin引起的,使用gdb调试一下看看
回复

使用道具 举报

千问 | 2021-1-27 06:52:07 | 显示全部楼层
二分查找吧,八成是哪里内存越界了,导致数据破坏,只不过最后看起来像是烂在getline里了。
回复

使用道具 举报

千问 | 2021-1-27 06:52:07 | 显示全部楼层
getline出这种问题,很有可能是你不知道getline如何工作的
getline在读的时候,是需要读到换行符的,但是它读到以后把换行符丢弃了。
因此,你输出getline的返回值的时候,看不到换行符输出,因为被它丢了,但是你执行getline的时候,必须给它一个有换行符的字符串,否则会有越界----它会一直往后读直至找到换行符

有几点要吐槽:
1)你不会提问。如果一个提问者发的代码行超过20行我一般一眼都不会看,你这样的提问题方式是在给别人布置任务,而不是在提问。
2)你太懒,不做基本的调试。代码出问题了,你应该先调试,一个一万行代码有一个报错,加断点一个一个找。另外,你还可以模拟一些数据,比如一万行代码的前五千行得到了10个数据,这10个数据会被后五千行用到,你调试的时可以先把前五千行注释掉,然后模拟这10个数据,传递给后五千行,看是否能得到预期的结果。按照这种方法,你可以很快定位错误点。而且,大多数情况下,只要你把错误点定位了,你就根本不需要问别人了.........就像你的这个问题,你并不是不会改错,而是你不知掉哪儿错了,你需要做的是找到错误的位置,仅此而已。这都懒得做,就别写代码了。
3)不知道你这是在干吗,但我还是想问一句:真的需要if嵌套那么多么........最好重新设计下......这种代码让别人来增删改的话,他十有八九会给你都删了他重写.........写出让别人有全部推倒重来的欲望的代码的程序员都是水货。
回复

使用道具 举报

千问 | 2021-1-27 06:52:07 | 显示全部楼层
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VSIDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。

回复

使用道具 举报

千问 | 2021-1-27 06:52:07 | 显示全部楼层
请问你的问题解决了吗,我在运行python程序时,进行矩阵运算也是遇到大于21维的矩阵会报段错误。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行