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

XSign 2015-09-17 10:57:19
首先说一下程序逻辑:
程序是提交到hadoop的streaming跑的c++程序.所以需要从stdin读取数据进行处理.而且每一次循环读入的数据都很大可能一行要达到5Mb左右的数据量.
现象是,
当处理少量数据时,程序可以正常结束,但是当处理大量数据时,hadoop报错,subprocess faild with code :11
也就是程序收到signal 11, 最终程序会产生segmention fault错误.
我加-g参数编译(gcc编译器),生成带符号的版本,等seg fault后,gdb -c加载dump文件,然后看堆栈调用,显示全部都是类似如下形式:
0xXXXXXXXX in ?? ()
看样子是调用到什么库里崩的.
然后我将程序逐行打log,发现是崩溃在getline这个c++的库函数调用里.非常不解是怎么回事,哪位高手能解答一下.

下面是程序的部分代码:

int main(int argc, char** argv){
Json::Reader json;
static csh handle;
cs_err cerr;
cerr = cs_open(CS_ARCH_X86, CS_MODE_32, &handle);
while(true){
std::string line;
printf("begin ... \n");
if(std::getline(std::cin, line)){
printf("parsing string ....\n");
size_t pos = line.find_last_of("\t");
printf("first find done ...\n");
if(pos != std::string::npos && line.find("file_content") != std::string::npos){
Json::Value output, json_data;
if(json.parse(line.substr(pos), json_data)){
pos = line.find_first_of("\t");
output["md5"] = line.substr(0, pos);
printf("json parse end ...\n");
std::string zip_buffer = base64_decode(json_data["file_content"].asString());
size_t file_buf_len = 0;
void* file_buf = (void*)unzip(zip_buffer.c_str(), zip_buffer.length(), (size_t*)&file_buf_len);
zip_buffer.clear();
printf("unzip end ... \n");
if(file_buf_len >= sizeof(IMAGE_DOS_HEADER)){
//check "MZ" signature
printf("checking MZ header ... \n");
if(*(unsigned short int*)(file_buf) == 0x5a4d){
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)file_buf;
//check "PE" signature
printf("checking PE header ... \n");
if(file_buf_len >= (dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS32)) && *(unsigned int*)((char*)file_buf + dos_header->e_lfanew) == 0x4550){
PIMAGE_NT_HEADERS32 nt_header = (PIMAGE_NT_HEADERS32)((char*)file_buf + dos_header->e_lfanew);
printf("getting section ... \n");
PIMAGE_SECTION_HEADER psh = get_section_header(file_buf, file_buf_len, nt_header->OptionalHeader.AddressOfEntryPoint);
printf("border check ... \n");
if(psh && file_buf_len >= psh->PointerToRawData + psh->SizeOfRawData){
cs_insn* insn;
unsigned int address = nt_header->OptionalHeader.AddressOfEntryPoint + nt_header->OptionalHeader.ImageBase;
size_t count = cs_disasm(handle, \
(uint8_t*)((char*)file_buf+RVA2OFFSET(nt_header->OptionalHeader.AddressOfEntryPoint,psh)), \
psh->PointerToRawData + psh->SizeOfRawData, \
address, 0, &insn);
for(size_t i = 0; i < count; ++i){
char szIns[520] = {0};
sprintf(szIns, "0x%x\t%s\t%s\n", insn[i].address, insn[i].mnemonic, insn[i].op_str);
output["asm"].append(szIns);
}
cs_free(insn, count);
std::cout<<output["md5"].asString()<<std::endl;
}
}
}
}
std::cout<<"free buffer ... "<<std::endl;
if(file_buf) free(file_buf);
}
}
std::cout<<"-------------------------------"<<std::endl;
line.resize(0);
}
}
return 0;
}


下面是崩溃时的log:

begin ...
parsing string ....
first find done ...
json parse end ...
unzip end ...
checking MZ header ...
checking PE header ...
getting section ...
border check ...
318e619313393266d4036b42815b5646
free buffer ...
-------------------------------
begin ...
parsing string ....
first find done ...
json parse end ...
unzip end ...
checking MZ header ...
checking PE header ...
getting section ...
border check ...
860582da12e4205474eb8a0fb49e556b
free buffer ...
-------------------------------
begin ...

[1]+ 段错误 nohup cat /data/sample.bin | ./asm > log.log 2>&1
...全文
457 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
sunny ray 2019-10-17
  • 打赏
  • 举报
回复
请问你的问题解决了吗,我在运行python程序时,进行矩阵运算也是遇到大于21维的矩阵会报段错误。
赵4老师 2015-09-18
  • 打赏
  • 举报
回复
进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈,内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件,参考“ulimit -c core文件最大块大小”命令
赵4老师 2015-09-18
  • 打赏
  • 举报
回复
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒:再牛×的老师也无法代替学生自己领悟和上厕所! 单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
bear234 2015-09-18
  • 打赏
  • 举报
回复
getline出这种问题,很有可能是你不知道getline如何工作的 getline在读的时候,是需要读到换行符的,但是它读到以后把换行符丢弃了。 因此,你输出getline的返回值的时候,看不到换行符输出,因为被它丢了,但是你执行getline的时候,必须给它一个有换行符的字符串,否则会有越界 ---- 它会一直往后读直至找到换行符 有几点要吐槽: 1)你不会提问。如果一个提问者发的代码行超过20行我一般一眼都不会看,你这样的提问题方式是在给别人布置任务,而不是在提问。 2)你太懒,不做基本的调试。代码出问题了,你应该先调试,一个一万行代码有一个报错,加断点一个一个找。另外,你还可以模拟一些数据,比如一万行代码的前五千行得到了10个数据,这10个数据会被后五千行用到,你调试的时可以先把前五千行注释掉,然后模拟这10个数据,传递给后五千行,看是否能得到预期的结果。按照这种方法,你可以很快定位错误点。而且,大多数情况下,只要你把错误点定位了,你就根本不需要问别人了.........就像你的这个问题,你并不是不会改错,而是你不知掉哪儿错了,你需要做的是找到错误的位置,仅此而已。这都懒得做,就别写代码了。 3)不知道你这是在干吗,但我还是想问一句:真的需要if嵌套那么多么........最好重新设计下......这种代码让别人来增删改的话,他十有八九会给你都删了他重写.........写出让别人有全部推倒重来的欲望的代码的程序员都是水货。
ri_aje 2015-09-18
  • 打赏
  • 举报
回复
二分查找吧,八成是哪里内存越界了,导致数据破坏,只不过最后看起来像是烂在 getline 里了。
ztenv 版主 2015-09-18
  • 打赏
  • 举报
回复
怀疑不是由cin引起的,使用gdb调试一下看看

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧