解除 Run-Time Check Failure #2

本文介绍在将VC6服务移植到VC7.1过程中遇到的运行时错误Run-Time Check Failure #2,并通过启用编译选项(/RTC1)检测到的堆栈溢出问题。通过对代码审查和修改,确保了字符串复制操作不会导致缓冲区溢出。

Run-Time Check Failure #2 - Stack around the variable 'var' was corrupted

摘要:
简介VC++.NET编译新功能,运行时错误检查,编译选项 (/RTC1, equiv. to /RTCsu)

最近把一个别人早期在VC 6下编写的一个服务移植到VC 7.1 (.NET 2003)时,突然跳出
好些运行时错误提示。
经过查询编译器和出错说明,发现了编译器的这一新特性,并修正了代码隐患:

//someheadefile.h
typedef struct tarSomeMessagePack
{
char moibleNumber[20];
....
}SomeMessagePack_T,*SomeMessagePack_Ptr;


细心的开发者可能已经发现,这里使用字符串数组下标越界了。即mobileNumber[]有效元素
下标为0到19,mobileNumber[20]是非法的。在VC 6下,编译运行并没有处任何问题,这也结
构体在内存字节对齐也有关系,实际上,mobileNumber[]在默认与8字节对齐的环境下编译链
接的,因此,后4个bit也不会被系统用到,即mobileNumber[20],mobileNumber[21],
mobileNumber[22],mobileNumber[23]系统把它空着。

尽管系统运行同几年都很正常,但
strncpy(pack.mobileNumber," ",20);
这样的代码也是危险的代码,要是有一天,把这个结构体字节对齐方式改为1,那么程序一定
在这里崩溃。

VC7.1为我们提供了一种机制,在编译选项中,增加(/RTC1, equiv. to /RTCsu)项选。当程序
运行到这里的时候,即会向我们报告这一错误。

查看相关文档,了解了这一块代码的真实意图后,我把代码改为
strncpy(pack.mobileNumber," ",19);

这一问题消失。

//someimplement.cpp

strncpy(pack.mobileNumber," ",20);

下列程序,我已经按你给我的办法创建了使用.sh脚本的开机自启,并且运行正常。使用journalctl -u chengpin-daizanting.service -f命令查看实时日志也显示程序正常运行,但是当我成功调用wav后,设备没有播放声音。 #!/usr/bin/env python3 import rclpy from rclpy.node import Node from sensor_msgs.msg import Joy import subprocess import os from threading import Thread import time class SoundPlayer(Node): def __init__(self): super().__init__(&#39;sound_player_node&#39;) # 参数配置 self.declare_parameter(&#39;audio_dir&#39;, &#39;/home/booster/Workspace/展会/新逻辑测试&#39;) # 音频文件目录 self.declare_parameter(&#39;trigger_button&#39;, 7) # 7号键索引(从0开始) # 初始化状态 self.recording = False # 记录模式标志 self.paused = False # 新增暂停状态标志 self.command_history = [] # 存储按键历史序列 self.current_command = set() # 当前按下的按键集合 self.audio_map = {} # 指令到音频文件的映射 self.last_button_state = [0]*20 # 记录按键上次状态 # 按键映射表 (0-9直接映射为数字) self.command_map = { 0: &#39;0&#39;, 1: &#39;1&#39;, 2: &#39;2&#39;, 3: &#39;3&#39;, 4: &#39;4&#39;, 5: &#39;5&#39;, 6: &#39;6&#39;, 7: &#39;7&#39;, 8: &#39;8&#39;, 9: &#39;9&#39; } # 加载音频文件 self.load_audio_files() # 订阅手柄输入 self.joy_sub = self.create_subscription( Joy, &#39;joy&#39;, self.joy_callback, 10 ) self.get_logger().info("Sound player node initialized. Press button 7 to start input...") def load_audio_files(self): """加载音频目录中的所有wav文件到内存""" audio_dir = os.path.expanduser( self.get_parameter(&#39;audio_dir&#39;).get_parameter_value().string_value ) if not os.path.exists(audio_dir): self.get_logger().error(f"Audio directory not found: {audio_dir}") return for filename in os.listdir(audio_dir): if filename.endswith(&#39;.wav&#39;): command = filename.split(&#39;.&#39;)[0] # 去掉扩展名作为指令名 self.audio_map[command] = os.path.join(audio_dir, filename) self.get_logger().info(f"Loaded audio: {command} -> {filename}") self.get_logger().info(f"Total {len(self.audio_map)} audio files loaded") def joy_callback(self, msg): """手柄按键回调函数""" # 如果程序处于暂停状态,只响应解除暂停指令 if self.paused: self.handle_paused_state(msg) return trigger_idx = self.get_parameter(&#39;trigger_button&#39;).get_parameter_value().integer_value # 确保状态数组足够长 if len(self.last_button_state) < len(msg.buttons): self.last_button_state = [0] * len(msg.buttons) # 检查7号键触发状态 if len(msg.buttons) > trigger_idx and msg.buttons[trigger_idx] == 1: if self.last_button_state[trigger_idx] == 0: # 检测上升沿 self.handle_trigger() self.last_button_state[trigger_idx] = 1 else: self.last_button_state[trigger_idx] = 0 # 记录模式下的按键检测 if self.recording: current_pressed = set() # 检测当前按下的按键 for idx, pressed in enumerate(msg.buttons): # 忽略触发键 if idx == trigger_idx: continue # 按键按下状态变化检测 if pressed == 1 and self.last_button_state[idx] == 0: # 记录按键按下 if idx in self.command_map: self.command_history.append(self.command_map[idx]) else: self.command_history.append(f"BTN{idx}") # 更新当前按下的按键集合 if pressed == 1: if idx in self.command_map: current_pressed.add(self.command_map[idx]) else: current_pressed.add(f"BTN{idx}") # 更新按键状态 self.last_button_state[idx] = pressed # 更新当前组合指令 self.current_command = current_pressed def handle_paused_state(self, msg): """处理暂停状态下的输入""" trigger_idx = self.get_parameter(&#39;trigger_button&#39;).get_parameter_value().integer_value # 确保状态数组足够长 if len(self.last_button_state) < len(msg.buttons): self.last_button_state = [0] * len(msg.buttons) # 只在按下触发键时检查解除暂停指令 if len(msg.buttons) > trigger_idx and msg.buttons[trigger_idx] == 1: if self.last_button_state[trigger_idx] == 0: # 检测上升沿 current_pressed = set() # 检测当前按下的按键 for idx, pressed in enumerate(msg.buttons): if idx == trigger_idx: continue if pressed == 1: if idx in self.command_map: current_pressed.add(self.command_map[idx]) else: current_pressed.add(f"BTN{idx}") # 检查是否是解除暂停指令(4-6) if &#39;4&#39; in current_pressed and &#39;6&#39; in current_pressed: self.paused = False self.get_logger().info("Program resumed") # 播放解除暂停的音效(如果有) if "4-6" in self.audio_map: Thread(target=self.play_audio, args=(self.audio_map["4-6"],)).start() self.last_button_state[trigger_idx] = 1 else: self.last_button_state[trigger_idx] = 0 def handle_trigger(self): """处理触发键按下事件""" if not self.recording: # 进入记录模式 self.recording = True self.command_history = [] # 清空历史 self.current_command = set() # 清空当前组合 self.get_logger().info("Recording STARTED. Input commands...") else: # 结束记录并执行指令 self.recording = False # 生成指令字符串 command_str = "" if self.current_command: # 当前组合按键指令 (如"0+1") command_str = "+".join(sorted(self.current_command)) elif self.command_history: # 历史序列按键指令 (如"0,1,2") command_str = "-".join(self.command_history) self.get_logger().info(f"Recording STOPPED. Executing: {command_str}") # 特殊指令处理:暂停程序 if command_str == "4-5": self.paused = True self.get_logger().info("Program paused") # 播放暂停音效(如果有) if "4-5" in self.audio_map: Thread(target=self.play_audio, args=(self.audio_map["4-5"],)).start() else: self.execute_command(command_str) def execute_command(self, command_str): """执行指令序列""" if command_str in self.audio_map: # 在新线程中播放音频避免阻塞 Thread(target=self.play_audio, args=(self.audio_map[command_str],)).start() else: self.get_logger().error(f"No audio found for command: [{command_str}]") def play_audio(self, file_path): """使用系统命令播放音频文件""" try: if os.path.exists(file_path): subprocess.run([&#39;aplay&#39;, &#39;-q&#39;, file_path], check=True) self.get_logger().info(f"Audio played: {file_path}") else: self.get_logger().error(f"Audio file not found: {file_path}") except Exception as e: self.get_logger().error(f"Playback failed: {str(e)}") def main(args=None): rclpy.init(args=args) node = SoundPlayer() try: rclpy.spin(node) except KeyboardInterrupt: pass finally: node.destroy_node() rclpy.shutdown() if __name__ == &#39;__main__&#39;: main()
最新发布
09-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值