Ubuntu Server下读取机器码二进制文件触发Segmentation Fault问题排查
程序Segmentation Fault问题排查与修复
在Linux Ubuntu Server环境下编写程序,目标是读取机器码二进制文件并解析输出汇编代码。程序运行至hexdump函数中cout << "inst " << (i+j) / 4 << ": ";语句后,出现**Segmentation Fault(core dumped)**错误导致执行终止,此前buflen(值为24)可正常打印。以下是原始代码(find、work函数暂未实现或未使用):
#include <fstream> #include <vector> #include <iostream> #include <algorithm> using namespace std; string find(char op[7]); void work(string inst, short* ins); void hexdump(void* ptr, const int buflen) { unsigned char* buf = (unsigned char*)ptr; int i, j, d, hex = 0; short* ins; string op; for (i = 0; i < buflen; i += 16) { for (j = 0; j < 16; j += 4) { if (i + j < buflen) { cout << buflen << endl; cout << "inst " << (i+j) / 4 << ": "; for (int a = 0; a < 32; a += 8) { d = buf[i + j + a / 8]; for (int k = 0; k < 8; k++) { if (d % 2 != 0) { ins[k + a] = 1; } else { ins[k + a] = 0; } d = d / 2; } } for (int i = 31; i >= 0; i -= 4) { hex = hex + ins[i] * 8; hex = hex + ins[i - 1] * 4; hex = hex + ins[i - 2] * 2; hex = hex + ins[i - 3] * 1; if (hex == 10) printf("a"); else if (hex == 11) printf("b"); else if (hex == 12) printf("c"); else if (hex == 13) printf("d"); else if (hex == 14) printf("e"); else if (hex == 15) printf("f"); else printf("%d", hex); hex = 0; } for (int i = 6; i >=0; i--) { if (ins[i] == 1) op.append("1"); else if (ins[i] == 0) op.append("0"); } cout << endl << op << endl; //work(find(op), ins); printf("\n"); } } } } int main(int argc, char* argv[]) { ifstream in; in.open(argv[1], ios::in | ios::binary); if (in.is_open()) { // get the starting position streampos start = in.tellg(); // go to the end in.seekg(0, std::ios::end); // get the ending position streampos end = in.tellg(); // go back to the start in.seekg(0, std::ios::beg); // create a vector to hold the data that // is resized to the total size of the file std::vector<char> contents; contents.resize(static_cast<size_t>(end - start)); // read it in in.read(&contents[0], contents.size()); // print it out (for clarity) hexdump(contents.data(), contents.size()); } in.close(); return 0; } string find(char op[7]) { string inst("unknown instruction"); if(op=="") return inst; } void work(string inst, short* ins);
错误原因分析
- 未初始化指针
ins:hexdump函数中仅声明short* ins;但未分配内存,直接对ins[k + a]赋值会访问非法内存,这是段错误的核心原因。 - 变量名冲突:内层循环使用
int i作为变量名,覆盖了外层循环的i,导致循环逻辑混乱。 op字符串未清空:每次循环后op会累积内容,导致后续输出错误。find函数参数类型不匹配:声明的find(char op[7])与调用时传入的string op类型不兼容。find函数缺少默认返回值:未满足所有分支的返回要求,存在未定义行为。
修复后的代码
#include <fstream> #include <vector> #include <iostream> #include <algorithm> using namespace std; string find(string op); void work(string inst, short* ins); void hexdump(void* ptr, const int buflen) { unsigned char* buf = (unsigned char*)ptr; int i, j, d, hex = 0; short ins[32]; // 直接分配固定大小数组,替代未初始化指针 string op; for (i = 0; i < buflen; i += 16) { for (j = 0; j < 16; j += 4) { if (i + j < buflen) { op.clear(); // 每次循环清空字符串 cout << buflen << endl; cout << "inst " << (i+j) / 4 << ": "; for (int a = 0; a < 32; a += 8) { d = buf[i + j + a / 8]; for (int k = 0; k < 8; k++) { ins[k + a] = (d % 2 != 0) ? 1 : 0; d /= 2; } } // 修改内层循环变量名,避免覆盖外层i for (int idx = 31; idx >= 0; idx -= 4) { hex = ins[idx] * 8 + ins[idx - 1] * 4 + ins[idx - 2] * 2 + ins[idx - 3] * 1; if (hex >= 10 && hex <= 15) printf("%c", 'a' + hex - 10); else printf("%d", hex); hex = 0; } // 修改内层循环变量名,避免覆盖外层i for (int idx = 6; idx >= 0; idx--) { op += (ins[idx] == 1) ? "1" : "0"; } cout << endl << op << endl; // work(find(op), ins); printf("\n"); } } } } int main(int argc, char* argv[]) { ifstream in; in.open(argv[1], ios::in | ios::binary); if (in.is_open()) { streampos start = in.tellg(); in.seekg(0, std::ios::end); streampos end = in.tellg(); in.seekg(0, std::ios::beg); std::vector<char> contents; contents.resize(static_cast<size_t>(end - start)); in.read(&contents[0], contents.size()); hexdump(contents.data(), contents.size()); } in.close(); return 0; } string find(string op) { string inst("unknown instruction"); if(op.empty()) return inst; return inst; // 补充默认返回值 } void work(string inst, short* ins) { // 后续实现指令解析逻辑 }
主要修改点
- 将
short* ins;改为short ins[32];,在栈上分配固定大小数组,避免非法内存访问。 - 修改内层循环变量名为
idx,避免覆盖外层循环的i变量。 - 每次处理指令前调用
op.clear(),清空字符串防止内容累积。 - 修正
find函数参数类型为string,使用op.empty()判断空字符串,并补充默认返回值。 - 简化十六进制输出逻辑,用
'a' + hex -10直接转换字母,代码更简洁。
内容的提问来源于stack exchange,提问作者newb hi
相关产品推荐
相关产品推荐

