显示 “0x004011a0"指令引用的“0 x00000000"内存。该内存不能为‘read". 要终止程序...

本文探讨了该内存不能为read或written错误的原因,从硬件故障如内存条问题到软件冲突,提供了详细的故障排查步骤及解决方案。
“0x????????”指令引用的“0x????????”内存。该内存不能为“read”。 
“0x????????”指令引用的“0x????????”内存,该内存不能为“written”。 

以上的情况相信大家都应该见到过,甚至说一些网友因为不爽于这个经常出现的错误提示而屡次重装系统。相信普通用户应该不会理解那些复杂的十六进制代码。 
出现这个现象有方面的,一是硬件,即内存方面有问题,二是软件,这就有多方面的问题了。 

一.先说说硬件: 
一般来说,电脑硬件是很不容易坏的。内存出现问题的可能性并不大(除非你的内存真的是杂牌的一塌徒地),主要方面是: 
1。内存条坏了(二手内存情况居多) 
2。使用了有质量问题的内存。 
3。内存插在主板上的金手指部分灰尘太多。 
4。使用不同品牌不同容量的内存,从而出现不兼容的情况。 
5。超频带来的散热问题。你可以使用MemTest 这个软件来检测一下内存,它可以彻底的检测出内存的稳定度。 

二、如果都没有,那就从软件方面排除故障了。 

先说原理:内存有个存放数据的地方叫缓冲区,当程序把数据放在缓冲区,需要操作系统提供的“功能函数”来申请,如果内存分配成功,函数就会将所新开辟的内存区地址返回给应用程序,应用程序就可以通过这个地址使用这块内存。这就是“动态内存分配”,内存地址也就是编程中的“光标”。内存不是永远都招之即来、用之不尽的,有时候内存分配也会失败。当分配失败时系统函数会返回一个0值,这时返回值“0”已不表示新启用的光标,而是系统向应用程序发出的一个通知,告知出现了错误。作为应用程序,在每一次申请内存后都应该检查返回值是否为0,如果是,则意味着出现了故障,应该采取一些措施挽救,这就增强了程序的“健壮性”。若应用程序没有检查这个错误,它就会按照“思维惯性”认为这个值是给它分配的可用光标,继续在之后的执行中使用这块内存。真正的0地址内存区储存的是计算机系统中最重要的“中断描述符表”,绝对不允许应用程序使用。在没有保护机制的操作系统下(如DOS),写数据到这个地址会导致立即当机,而在健壮的操作系统中,如Windows等,这个操作会马上被系统的保护机制捕获,其结果就是由操作系统强行关闭出错的应用程序,以防止其错误扩大。这时候,就会出现上述的内存不能为“read”错误,并指出被引用的内存地址为“0x00000000“。内存分配失败故障的原因很多,内存不够、系统函数的版本不匹配等都可能有影响。因此,这种分配失败多见于操作系统使用很长时间后,安装了多种应用程序(包括无意中“安装”的病毒程序),更改了大量的系统参数和系统档案之后。 

在使用动态分配的应用程序中,有时会有这样的情况出现:程序试图读写一块“应该可用”的内存,但不知为什么,这个预料中可用的光标已经失效了。有可能是“忘记了”向操作系统要求分配,也可能是程序自己在某个时候已经注销了这块内存而“没有留意”等等。注销了的内存被系统回收,其访问权已经不属于该应用程序,因此读写操作也同样会触发系统的保护机制,企图“违法”的程序唯一的下场就是被操作终止执行,回收全部资源。计算机世界的法律还是要比人类有效和严厉得多啊!像这样的情况都属于程序自身的BUG,你往往可在特定的操作顺序下重现错误。无效光标不一定总是0,因此错误提示中的内存地址也不一定为“0x00000000”,而是其它随机数字。 

首先建议: 
1、 检查系统中是否有木马或病毒。这类程序为了控制系统往往不负责任地修改系统,从而导致操作系统异常。平常应加强信息安全意识,对来源不明的可执行程序绝不好奇。 
2、 更新操作系统,让操作系统的安装程序重新拷贝正确版本的系统档案、修正系统参数。有时候操作系统本身也会有BUG,要注意安装官方发行的升级程序。 
3、 尽量使用最新正式版本的应用程序、Beta版、试用版都会有BUG。 
4、 删除然后重新创建 Winnt\System32\Wbem\Repository 文件夹中的文件:在桌面上右击我的电脑,然后单击管理。 在"服务和应用程序"下,单击服务,然后关闭并停止 Windows Management Instrumentation 服务。 删除 Winnt\System32\Wbem\Repository 文件夹中的所有文件。(在删除前请创建这些文件的备份副本。) 打开"服务和应用程序",单击服务,然后打开并启动 Windows Management Instrumentation 服务。当服务重新启动时,将基于以下注册表项中所提供的信息重新创建这些文件: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\CIMOM\Autorecover MOFs
_Z16read_sensor_datav 0x04dfb21c: 49fe .I LDR r1,[pc,#1016] ; [0x4dfb618] = 0x50ee34c 0x04dfb21e: 223a :" MOVS r2,#0x3a 0x04dfb220: a0fe .. ADR r0,{pc}+0x3fc ; 0x4dfb61c 0x04dfb222: b508 .. PUSH {r3,lr} 0x04dfb224: f605f88d .... BL fatal_printf ; 0x4c00342 0x04dfb228: 20e1 . MOVS r0,#0xe1 0x04dfb22a: 9000 .. STR r0,[sp,#0] 0x04dfb22c: 2004 . MOVS r0,#4 0x04dfb22e: f28fec70 ..p. BLX $Ven$AA$S$$__cxa_allocate_exception ; 0x508ab10 0x04dfb232: 9900 .. LDR r1,[sp,#0] 0x04dfb234: 2200 ." MOVS r2,#0 0x04dfb236: 6001 .` STR r1,[r0,#0] 0x04dfb238: 49fc .I LDR r1,[pc,#1008] ; [0x4dfb62c] = 0x54547b4 0x04dfb23a: f28fec6c ..l. BLX $Ven$AA$S$$__cxa_throw ; 0x508ab14 _Z12process_datav 0x04dfb23e: 49f6 .I LDR r1,[pc,#984] ; [0x4dfb618] = 0x50ee34c 0x04dfb240: 2240 @" MOVS r2,#0x40 0x04dfb242: a0f6 .. ADR r0,{pc}+0x3da ; 0x4dfb61c 0x04dfb244: 3111 .1 ADDS r1,r1,#0x11 0x04dfb246: b510 .. PUSH {r4,lr} 0x04dfb248: f605f87b ..{. BL fatal_printf ; 0x4c00342 0x04dfb24c: f7ffffe6 .... BL _Z16read_sensor_datav ; 0x4dfb21c 0x04dfb250: 49f1 .I LDR r1,[pc,#964] ; [0x4dfb618] = 0x50ee34c 0x04dfb252: 2242 B" MOVS r2,#0x42 0x04dfb254: a0f1 .. ADR r0,{pc}+0x3c8 ; 0x4dfb61c 0x04dfb256: 3111 .1 ADDS r1,r1,#0x11 0x04dfb258: f605f873 ..s. BL fatal_printf ; 0x4c00342 0x04dfb25c: bd10 .. POP {r4,pc} 0x04dfb25e: f28fec5c ..\. BLX $Ven$AA$S$$__cxa_begin_catch ; 0x508ab18 0x04dfb262: 2245 E" MOVS r2,#0x45 0x04dfb264: e002 .. B 0x4dfb26c ; _Z12process_datav + 46 0x04dfb266: f28fec58 ..X. BLX $Ven$AA$S$$__cxa_begin_catch ; 0x508ab18 0x04dfb26a: 224b K" MOVS r2,#0x4b 0x04dfb26c: 49ea .I LDR r1,[pc,#936] ; [0x4dfb618] = 0x50ee34c 0x04dfb26e: a0eb .. ADR r0,{pc}+0x3ae ; 0x4dfb61c 0x04dfb270: 3111 .1 ADDS r1,r1,#0x11 0x04dfb272: f605f866 ..f. BL fatal_printf ; 0x4c00342 0x04dfb276: f28fec52 ..R. BLX $Ven$AA$S$$__cxa_end_catch ; 0x508ab1c 0x04dfb27a: bd10 .. POP {r4,pc}
最新发布
11-29
.data prompt: .asciiz "Input MIPS machine code: " error_msg: .asciiz "Error: Invalid instruction format.\n" result_msg: .asciiz "\nMIPS Assembly:\n" instr_loaded: .asciiz " instructions loaded\n" reg_names: .asciiz "$zero,$at,$v0,$v1,$a0,$a1,$a2,$a3,$t0,$t1,$t2,$t3,$t4,$t5,$t6,$t7,$s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$t8,$t9,$k0,$k1,$gp,$sp,$fp,$ra" buffer: .space 64 # 用于存储反汇编结果 input_buffer: .space 1024 # 输入缓冲区 instr_buffer: .space 400 # 指令缓冲区 (100指令) pc_base: .word 0x00400000 # 程序计数器基址 unknown_instr: .asciiz "???" unknown_reg: .asciiz "???" add_op: .asciiz "add " sub_op: .asciiz "sub " addi_op: .asciiz "addi " comma_space: .asciiz ", " neg_sign: .asciiz "-" num_buffer: .space 16 space: .asciiz " " newline: .asciiz "\n" max_instructions_val: .word 100 instruction_size_val: .word 8 # 全局变量 instructionCount: .word 0 # 指令数量 instructions: .word 0 # 指令数组基址 .text .globl main main: # 初始化指令缓冲区地址 la $t0, instr_buffer sw $t0, instructions # 调用 readInstructions jal readInstructions # 调用 printResult jal printResult # 退出程序 li $v0, 10 syscall # 函数: readInstructions readInstructions: # 保存寄存器上下文 addi $sp, $sp, -20 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) sw $s2, 12($sp) sw $s3, 16($sp) # 打印提示信息 li $v0, 4 la $a0, prompt syscall # 读取输入 la $a0, input_buffer li $a1, 1024 li $v0, 8 syscall # 初始化变量 la $s0, input_buffer # 输入缓冲区地址 la $s1, instr_buffer # 指令缓冲区地址 # 确保缓冲区地址对齐(新增代码) andi $t0, $s1, 0x3 # 检查地址是否对齐 bnez $t0, align_buffer li $s2, 0 # 指令计数器 read_loop: # 从内存加载常量值 lw $t0, max_instructions_val bge $s2, $t0, read_done # 查找下一个空格或字符串结束符 lb $t0, 0($s0) beqz $t0, read_done # 字符串结束 beq $t0, ' ', skip_space # 解析指令 move $a0, $s0 jal parse_hex_instruction move $t1, $v0 # 解析结果 # 从内存加载常量值 lw $t2, instruction_size_val bne $t1, $t2, invalid_instruction # 转换十六进制字符串为整数 move $a0, $s0 jal hex_str_to_int move $t3, $v0 # 转换后的指令值 # 计算存储地址(修复对齐问题) sll $t4, $s2, 2 # 计算偏移量 (×4) add $t5, $s1, $t4 # 目标地址 # 保存指令到缓冲区(修复后的对齐逻辑) sw $t3, 0($t5) # 存储指令 # 更新指令计数器 addi $s2, $s2, 1 skip_space: addi $s0, $s0, 1 # 移动到下一个字符 j read_loop invalid_instruction: li $v0, 4 la $a0, error_msg syscall j skip_space # 跳过当前无效指令 align_buffer: # 调整缓冲区地址使其对齐到4字节边界 li $t6, 4 # 加载常量4 sub $t6, $t6, $t0 # 计算需要调整的字节数 # 检查调整后的地址是否超出缓冲区范围 la $t7, instr_buffer # 获取缓冲区起始地址 la $t8, instr_buffer # 获取缓冲区结束地址 addi $t8, $t8, 400 # 缓冲区大小为400字节 add $t9, $t7, $t6 # 计算调整后的地址 bge $t9, $t8, align_error # 如果超出范围,跳转到错误处理 # 使用add指令代替addi,避免立即数表达式问题 add $s1, $s1, $t6 # 正确调整缓冲区地址 # 验证调整后的地址是否对齐 andi $t0, $s1, 0x3 # 重新检查对齐 bnez $t0, align_buffer # 如果仍未对齐,继续调整(理论上不会执行 j read_loop align_error: # 处理地址超出范围的错误 li $v0, 4 la $a0, error_msg syscall li $v0, 10 # 退出程序 syscall read_done: # 保存指令数量到全局变量 sw $s2, instructionCount # 恢复寄存器上下文并返回 lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) lw $s2, 12($sp) lw $s3, 16($sp) addi $sp, $sp, 20 jr $ra # 函数: parse_hex_instruction # 输入: $a0 = 字符串地址 # 输出: $v0 = 指令长度(字符数) parse_hex_instruction: addi $sp, $sp, -4 sw $s0, 0($sp) move $s0, $a0 # 保存字符串地址 li $v0, 0 # 长度计数器 parse_loop: lb $t0, 0($s0) beqz $t0, parse_done # 字符串结束 beq $t0, ' ', parse_done # 空格分隔 addi $v0, $v0, 1 # 长度加1 addi $s0, $s0, 1 # 移动到下一个字符 j parse_loop parse_done: lw $s0, 0($sp) addi $sp, $sp, 4 jr $ra # 函数: hex_str_to_int # 输入: $a0 = 字符串地址 # 输出: $v0 = 转换后的整数 hex_str_to_int: addi $sp, $sp, -12 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) move $s0, $a0 # 保存字符串地址 li $s1, 0 # 结果 hex_loop: lb $t0, 0($s0) beqz $t0, hex_done # 字符串结束 beq $t0, ' ', hex_done # 空格分隔 # 转换单个字符 move $a0, $t0 jal char_to_hex move $t1, $v0 # 字符对应的十六进制值 # 更新结果 sll $s1, $s1, 4 # 左移4位 or $s1, $s1, $t1 # 合并当前字符的值 addi $s0, $s0, 1 # 移动到下一个字符 j hex_loop hex_done: move $v0, $s1 # 返回结果 lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) addi $sp, $sp, 12 jr $ra # 函数: char_to_hex # 输入: $a0 = 字符 # 输出: $v0 = 对应的十六进制值 (0-15) char_to_hex: li $v0, -1 # 默认返回-1(错误) # 检查是否为数字 blt $a0, '0', check_alpha ble $a0, '9', is_digit check_alpha: # 检查是否为大写字母 blt $a0, 'A', check_lower ble $a0, 'F', is_upper check_lower: # 检查是否为小写字母 blt $a0, 'a', char_done ble $a0, 'f', is_lower char_done: jr $ra is_digit: sub $v0, $a0, '0' # '0'→0, '1'→1, ..., '9'→9 jr $ra is_upper: sub $v0, $a0, 'A' # 'A'→0, 'B'→1, ..., 'F'→5 addi $v0, $v0, 10 # 转换为10-15 jr $ra is_lower: sub $v0, $a0, 'a' # 'a'→0, 'b'→1, ..., 'f'→5 addi $v0, $v0, 10 # 转换为10-15 jr $ra # 函数: disassembleInstruction # 输入: $a0 = 指令值, $a1 = 结果缓冲区地址 # 输出: 无 disassembleInstruction: addi $sp, $sp, -24 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) sw $s2, 12($sp) sw $s3, 16($sp) sw $s4, 20($sp) move $s0, $a0 # 保存指令值 move $s1, $a1 # 保存结果缓冲区地址 # 提取opcode srl $t0, $s0, 26 andi $t0, $t0, 0x3F move $s2, $t0 # 保存opcode # 判断指令类型 beq $s2, 0, handle_r_type # R-type # 处理I-type指令 beq $s2, 0x08, handle_addi # addi # 未知指令 la $t1, unknown_instr jal strcpy j disasm_done handle_r_type: # 提取R-type字段 srl $t0, $s0, 21 andi $s3, $t0, 0x1F # rs srl $t0, $s0, 16 andi $s4, $t0, 0x1F # rt srl $t0, $s0, 11 andi $t1, $t0, 0x1F # rd andi $t2, $s0, 0x3F # funct # 判断funct字段 beq $t2, 0x20, handle_add # add beq $t2, 0x22, handle_sub # sub # 未知R-type指令 la $t1, unknown_instr jal strcpy j disasm_done handle_add: la $t1, add_op jal strcpy # 添加目标寄存器 move $a0, $t1 jal get_reg_name jal strcpy # 添加逗号和空格 la $t1, comma_space jal strcpy # 添加源寄存器1 move $a0, $s3 jal get_reg_name jal strcpy # 添加逗号和空格 la $t1, comma_space jal strcpy # 添加源寄存器2 move $a0, $s4 jal get_reg_name jal strcpy j disasm_done handle_sub: la $t1, sub_op jal strcpy # 添加目标寄存器 move $a0, $t1 jal get_reg_name jal strcpy # 添加逗号和空格 la $t1, comma_space jal strcpy # 添加源寄存器1 move $a0, $s3 jal get_reg_name jal strcpy # 添加逗号和空格 la $t1, comma_space jal strcpy # 添加源寄存器2 move $a0, $s4 jal get_reg_name jal strcpy j disasm_done handle_addi: la $t1, addi_op jal strcpy # 添加目标寄存器 move $a0, $s4 jal get_reg_name jal strcpy # 添加逗号和空格 la $t1, comma_space jal strcpy # 添加源寄存器 move $a0, $s3 jal get_reg_name jal strcpy # 添加逗号和空格 la $t1, comma_space jal strcpy # 提取并添加立即数 andi $t3, $s0, 0xFFFF # 提取16位立即数 move $a0, $t3 move $a1, $s1 jal print_imm move $s1, $a1 # 更新缓冲区指针 j disasm_done disasm_done: lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) lw $s2, 12($sp) lw $s3, 16($sp) lw $s4, 20($sp) addi $sp, $sp, 24 jr $ra # 函数: getRegisterName # 输入: $a0 = 寄存器编号 # 输出: $v0 = 寄存器名称地址 get_reg_name: addi $sp, $sp, -4 sw $s0, 0($sp) li $v0, 0 # 初始化返回值为0 # 检查寄存器编号是否有效 blt $a0, 0, reg_done bge $a0, 32, reg_done # 计算寄存器名称偏移 la $s0, reg_names sll $t0, $a0, 2 # 每个名称占4字节(包括逗号) add $v0, $s0, $t0 # 跳过前导逗号 lb $t1, 0($v0) beq $t1, ',', skip_comma j reg_done skip_comma: addi $v0, $v0, 1 # 跳过逗号 reg_done: lw $s0, 0($sp) addi $sp, $sp, 4 jr $ra # 函数: printResult printResult: addi $sp, $sp, -20 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) sw $s2, 12($sp) sw $s3, 16($sp) # 打印结果标题 li $v0, 4 la $a0, result_msg syscall # 获取指令数量 lw $s0, instructionCount beqz $s0, print_done # 打印指令数量 li $v0, 1 move $a0, $s0 syscall li $v0, 4 la $a0, instr_loaded syscall # 初始化循环变量 li $s1, 0 # 指令索引 la $s2, instr_buffer # 指令缓冲区地址 lw $s3, pc_base # PC基址 print_loop: bge $s1, $s0, print_done # 计算指令地址 sll $t0, $s1, 2 # 偏移量 = 索引 × 4 add $t1, $s2, $t0 # 指令实际地址 andi $t8, $t1, 0x3 bnez $t8, print_error # 如果未对齐,跳转到错误 lw $t2, 0($t1) # 加载指令 # 计算PC值 add $t3, $s3, $t0 # PC = 基址 + 偏移量 # 打印PC值(十六进制) li $v0, 34 move $a0, $t3 syscall # 打印空格 li $v0, 4 la $a0, space syscall # 反汇编指令 la $a1, buffer move $a0, $t2 jal disassembleInstruction # 打印反汇编结果 li $v0, 4 la $a0, buffer syscall # 打印换行 li $v0, 4 la $a0, newline syscall # 更新索引 addi $s1, $s1, 1 j print_loop print_error: # 处理地址未对齐的错误 li $v0, 4 la $a0, error_msg syscall li $v0, 10 # 退出程序 syscall print_done: lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) lw $s2, 12($sp) lw $s3, 16($sp) addi $sp, $sp, 20 jr $ra # 函数: strcpy # 输入: $t1 = 源字符串地址, $s1 = 目标缓冲区地址 # 输出: 更新后的$s1 = 目标缓冲区地址 strcpy: lb $t2, 0($t1) beqz $t2, strcpy_done sb $t2, 0($s1) addi $t1, $t1, 1 addi $s1, $s1, 1 j strcpy strcpy_done: jr $ra # 函数: print_imm # 输入: $a0 = 立即数值, $a1 = 缓冲区地址 # 输出: $a1 = 更新后的缓冲区地址 print_imm: addi $sp, $sp, -12 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) move $s0, $a0 # 保存立即数 move $s1, $a1 # 保存缓冲区地址 # 检查是否为负数 bgez $s0, print_positive # 处理负数 la $t0, neg_sign lb $t1, 0($t0) sb $t1, 0($s1) addi $s1, $s1, 1 neg $s0, $s0 # 取绝对值 print_positive: # 将数字转换为字符串 li $t0, 10 la $t1, num_buffer li $t2, 0 # 数字位数 digit_loop: div $s0, $t0 mfhi $t3 # 余数 = 当前位 mflo $s0 # 商 = 剩余数字 addi $t3, $t3, '0' # 转换为ASCII add $t4, $t1, $t2 sb $t3, 0($t4) addi $t2, $t2, 1 bnez $s0, digit_loop # 反转数字字符串 addi $t2, $t2, -1 # 指向最后一位 reverse_loop: add $t4, $t1, $t2 lb $t3, 0($t4) sb $t3, 0($s1) addi $s1, $s1, 1 addi $t2, $t2, -1 bgez $t2, reverse_loop # 添加字符串结束符 sb $zero, 0($s1) move $a1, $s1 # 返回更新后的缓冲区地址 lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) addi $sp, $sp, 12 jr $ra 出现错误:
05-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值