Don’t Ignore That Error!

本文通过一个日常生活中的例子,强调了在编程中及时处理错误的重要性。忽视错误可能导致代码质量下降、安全性问题、结构不佳等严重后果。文章详细讨论了如何正确处理错误,包括使用返回代码、errno、异常等方法,并提供了避免常见错误处理陷阱的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Don’t Ignore That Error!

Pete Goodliffe

I was walking down the street one evening to meet some friends in a bar. We hadn’t shared a beer in some time, and I was looking forward to seeing them again. In my haste, I wasn’t looking where I was going. I tripped over the edge of a curb and ended up flat on my face. Well, it serves me right for not paying attention, I guess.
It hurt my leg, but I was in a hurry to meet my friends. So, I pulled myself up and carried on. As I walked farther, the pain was getting worse. Although I’d initially dismissed it as shock, I rapidly realized there was something wrong.
But I hurried on to the bar regardless. I was in agony by the time I arrived. I didn’t have a great night out, because I was terribly distracted. In the morning, I went to the doctor and found out I’d fractured my shin bone. Had I stopped when I felt the pain, I would’ve prevented a lot of extra damage that I caused by walking on it. Probably the worst morning after of my life.
TOO MANY PROGRAMMERS write code like my disastrous night out.
Error, what error? It won’t be serious. Honestly. I can ignore it. This is not a win- ning strategy for solid code. In fact, it’s just plain laziness. (The wrong sort.) No matter how unlikely you think an error is in your code, you should always check for it, and always handle it. Every time. You’re not saving time if you don’t; you’re storing up potential problems for the future.
We report errors in our code in a number of ways, including:
• Return codes can be used as the resulting value of a function to mean “it didn’t work.” Error return codes are far too easy to ignore. You won’t see anything in the code to highlight the problem. Indeed, it’s become normal practice to ignore some standard C functions’ return values. How often do you check the return value from printf?
• errno is a curious C aberration, a separate global variable set to sig- nal error. It’s easy to ignore, hard to use, and leads to all sorts of nasty problems—for example, what happens when you have multiple threads
52 97 Things Every Programmer Should Know

calling the same function? Some platforms insulate you from pain here; others do not.
• Exceptions are a more structured language-supported way of signaling and handling errors. And you can’t possibly ignore them. Or can you? I’ve seen lots of code like this:
try {
// …do something…
}
catch (…) {} // ignore errors
The saving grace of this awful construct is that it highlights the fact that you’re doing something morally dubious.
If you ignore an error, turn a blind eye, and pretend that nothing has gone wrong, you run great risks. Just as my leg ended up in a worse state than if I’d stopped walking on it immediately, plowing on regardless of the red flags can lead to very complex failures. Deal with problems at the earliest opportunity. Keep a short account.
Not handling errors leads to:
• Brittle code. Code that’s filled with exciting, hard-to-find bugs.
• Insecure code. Crackers often exploit poor error handling to break into software systems.
• Poor structure. If there are errors from your code that are tedious to deal with continually, you probably have a poor interface. Express it so that the errors are less intrusive and their handling is less onerous.
Just as you should check all potential errors in your code, you need to expose all potentially erroneous conditions in your interfaces. Do not hide them, pre- tending that your services will always work.
Why don’t we check for errors? There are a number of common excuses. Which of these do you agree with? How would you counter each one?
• Error handling clutters up the flow of the code, making it harder to read, and harder to spot the “normal” flow of execution.
• It’s extra work, and I have a deadline looming.
• I know that this function call will never return an error (printf always works, malloc always returns new memory—if it fails, we have bigger problems…).
• It’s only a toy program, and needn’t be written to a production-worthy level.

from face_tracking import servos from maix import image, camera, display, time, nn, touchscreen ### model path MODEL = "/root/models/retinaface.mud" class Target: """Obtain the error value between the target and the center point. Need to modify __init__() and __get_target(). Args: out_range (float): output range ignore_limit (float): dead zone path (str): model path """ def __init__(self, out_range:float, ignore_limit:float, path:str): """Constructor Initialization of the recognition model class or other classes needs to be implemented here. """ self.pitch = 0 self.roll = 0 self.out_range = out_range self.ignore = ignore_limit ### Self.w and self.h must be initialized. self.detector = nn.Retinaface(model=path) self.w = self.detector.input_width() self.h = self.detector.input_height() self.cam = camera.Camera(self.w, self.h) self.disp = display.Display() ### The following section is used as an opt-out and normally you do not need to modify it. self.ts = touchscreen.TouchScreen() self.img_exit = image.load("./assets/exit.jpg").resize(40, 40) self.img_exit_touch = image.load("./assets/exit_touch.jpg").resize(40, 40) self.box = [0, 0, self.img_exit.width(), self.img_exit.height()] self.need_exit = False def __check_touch_box(self, t, box, oft = 0): """This method is used for exiting and you normally do not need to modify or call it. You usually don't need to modify it. """ if t[2] and t[0] + oft > box[0] and t[0] < box[0] + box[2] + oft and t[1] + oft > box[1] and t[1] < box[1] + box[3] + oft: return True else: return False def __exit_listener(self, img): """Exit case detection methods. It also draws the Exit button in the upper left corner. You usually don't need to modify it. Args: img (image.Image): The image that needs to be drawn. """ t = self.ts.read() if self.__check_touch_box(t, self.box, 20): img.draw_image(self.box[0], self.box[1], self.img_exit_touch) self.need_exit = True else: img.draw_image(self.box[0], self.box[1], self.img_exit) def is_need_exit(self): """Queries whether the exit button has been pressed. You usually don't need to modify it. Returns: bool: Returns true if the exit button has been pressed, false otherwise. """ return self.need_exit def __get_target(self): """Get the coordinate value of the target. The behavior of this function needs to be customized. Returns: int, int: If no target is found, return -1,-1. If the target is found, return the coordinate values x,y of the center point of the target. """ ltime = time.ticks_ms() img = self.cam.read() # Reads an image frame. objs = self.detector.detect(img, conf_th = 0.4, iou_th = 0.45) # Recognition. for obj in objs: # Find objects. img.draw_rect(obj.x, obj.y, obj.w, obj.h, image.COLOR_RED, 2) cent_x = obj.x + round(obj.w/2) # Calculate the x-coordinate of the target center point. cent_y = obj.y + round(obj.h/2) # Calculate the y-coordinate of the target center point. img.draw_rect(cent_x-1, cent_y-1, 2, 2, image.COLOR_GREEN) rtime = time.ticks_ms() # print(f"find target used time:{round(rtime-ltime,2)}ms") self.__exit_listener(img) # Queries whether the Exit button was pressed. self.disp.show(img) # Display this image. return cent_x, cent_y # Return (x, y) self.__exit_listener(img) self.disp.show(img) return -1, -1 # Target not found. Return (-1, -1) def get_target_err(self): """Obtain the error value between the target and the center point. You usually don't need to modify it. Returns: int, int: y-axis error value, x-axis error value. """ cent_x, cent_y = self.__get_target() if cent_x == -1: return (0, 0) self.pitch = cent_y / self.h * self.out_range * 2 - self.out_range self.roll = cent_x / self.w * self.out_range * 2 - self.out_range if abs(self.pitch) < self.out_range*self.ignore: self.pitch = 0 if abs(self.roll) < self.out_range*self.ignore: self.roll = 0 return self.pitch, self.roll if __name__ == '__main__': ROLL_PWM_PIN_NAME = "A17" PITCH_PWM_PIN_NAME = "A16" init_pitch = 150 # init position, value: [0, 100], means minimum angle to maxmum angle of servo init_roll = 150 # 50 means middle PITCH_DUTY_MIN = 3.5 # The minimum duty cycle corresponding to the range of motion of the y-axis servo. PITCH_DUTY_MAX = 9.5 # Maximum duty cycle corresponding to the y-axis servo motion range. ROLL_DUTY_MIN = 2.5 # Minimum duty cycle for x-axis servos. ROLL_DUTY_MAX = 12.5 # Maxmum duty cycle for x-axis servos. pitch_pid = [0.3, 0.0001, 0.0018, 0] # [P I D I_max] roll_pid = [0.3, 0.0001, 0.0018, 0] # [P I D I_max] target_err_range = 10 # target error output range, default [0, 10] target_ignore_limit = 0.08 # when target error < target_err_range*target_ignore_limit , set target error to 0 pitch_reverse = False # reverse out value direction roll_reverse = True # reverse out value direction target = Target(target_err_range, target_ignore_limit, MODEL) try: roll = servos.Servos(ROLL_PWM_PIN_NAME, init_roll, ROLL_DUTY_MIN, ROLL_DUTY_MAX) pitch = servos.Servos(PITCH_PWM_PIN_NAME, init_pitch, PITCH_DUTY_MIN, PITCH_DUTY_MAX) except RuntimeError as e: print(f"!!!!!!!!!!!!!!!! ERROR: {e} !!!!!!!!!!!!!!!!!!!!!!") wait_time_s = 10 while wait_time_s: eimg = image.Image(target.w, target.h) eimg.draw_string(10, 10, "Error: "+str(e)+ f". This program will exit after {wait_time_s}s.") target.disp.show(eimg) time.sleep(1) wait_time_s -= 1 exit(-1) pid_pitch = servos.PID(p=pitch_pid[0], i=pitch_pid[1], d=pitch_pid[2], imax=pitch_pid[3]) pid_roll = servos.PID(p=roll_pid[0], i=roll_pid[1], d=roll_pid[2], imax=roll_pid[3]) gimbal = servos.Gimbal(pitch, pid_pitch, roll, pid_roll) total_uesd_time = 0 total_fps = 0 t0 = time.ticks_ms() while not target.is_need_exit(): ltime = time.ticks_ms() # get target error err_pitch, err_roll = target.get_target_err() # interval limit to >= 10ms if time.ticks_ms() - t0 < 10: continue t0 = time.ticks_ms() # run gimbal.run(err_pitch, err_roll, pitch_reverse = pitch_reverse, roll_reverse=roll_reverse) # Calculate FPS. rtime = time.ticks_ms() utime = rtime-ltime total_uesd_time += utime total_fps += 1 print(f"used time:{utime}ms, fps:{round(1000/(utime),2)}, avg_fps:{round(total_fps*1000/total_uesd_time, 2)}") 找出这段代码中哪些是确定坐标的
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值