Отладка трудно воспроизводимой ошибки C. Динамическая точка останова

Мне трудно воссоздать ошибку, и я надеюсь использовать python GDB script, чтобы остановить процесс при обнаружении ошибки (я буду запускать ее в режиме отладки, пока ошибка не будет восстановлена). В отношении Блуждающих символов, видимых вне snprintf.

В настоящее время я сделал скрипт, который может создавать break-point и параллельно читать терминал serial для обнаружения ошибки в строке. Вот сценарий:

from __future__ import print_function
import serial
import pandas as pd
import argparse
import io
import time
import ast
import sys
import signal
import threading


class Serial_Port():
    def __init__(self, port_number, baud_rate):
        self.ser = serial.Serial(port_number, baud_rate, timeout=10)
        self.ser_io = io.TextIOWrapper(io.BufferedRWPair(self.ser, self.ser, 1), newline = '\r', line_buffering = True)
        self.data_count = 0
        self.data_times = 0
        self.data_succ = 0
        self.ifPrint = False

    def read(self):
        raw_line = self.ser_io.readline()
        raw_line = raw_line.strip("\x00")
        raw_line = raw_line.strip("\r\n")

        if self.ifPrint == True:
            fptr.write(raw_line)
        else:
            self.data_times +=1
            # Print the current status of string test
            to_write = "Loop: %d Read Count: %d Successful: %d" % (self.data_times, self.data_count, self.data_succ)
            fptr.write(to_write)
            fptr.write("\n")


        if "[[" in raw_line:
            self.data_count += 1
            self.parse(raw_line)
        #Flush all the data before returning
        fptr.flush()

    def parse(self, gnss):
        try:
            #if we are able to convert literal and a DF made
            # we'll assume the data received is valid
            gnss = ast.literal_eval(gnss)
            df = pd.DataFrame(gnss)
            self.data_succ += 1
        except KeyboardInterrupt:
            self.ser.flush()
            self.ser.close()
            sys.exit(0)
        except:
            fptr.write(gnss)
            fptr.write("\n")
            fptr.flush()

    def close(self, frame, andsomething):
        self.ser.flush()
        self.ser.close()
        sys.exit(0)

class DebugPrintingBreakpoint(gdb.Breakpoint):
    debugging_IDs = frozenset({37, 153, 420})
    def stop(self):
        top = gdb.newest_frame()
        someVector = top.read_var('aVectorVar')
        # Access the begin() & end() pointer of std::vector in GNU Standard C++ lib
        first = someVector['_M_impl']['_M_start']
        last = someVector['_M_impl']['_M_finish']
        values = []
        while first != last:
            values.append(int(first.dereference()['intID']))
            first = first + 1
        if not set(values) & debugging_IDs:
            return False # skip: none of the items we're looking for can be found by ID in the vector on the stack
        print("Found other accompanying IDs: {}".format(values))
        return True # drop to gdb's prompt

class MyThread_serial(threading.Thread):
    def run(self):

        while True:
            time.sleep(1)#sleep for 1s
            serialPort.read()

def main():
    ser_thread = MyThread_serial(name = "Thread-serial")
    ser_thread.start()

    gdb.execute("continue")

if __name__ == "__main__":
    fptr = open("gdbOPs.txt", "a") 

    #connect to serial port
    strPort = "/dev/ttyUSB0"
    serialPort = Serial_Port(strPort, 9600)

    #set signal interrupt to exit
    signal.signal(signal.SIGINT, serialPort.close)
    print('Press Ctrl+C to exit')

    main()

Фон

У меня есть оборудование, которое отправляет строку в формате

[[12.12345678,12.12345678],[12.12345678,12.12345678],...]

Но иногда в строке могут быть ошибки, подобные

[[12.12345678,12.12345678],[55.01[12.12345678,12.12345678],...]

Мне никогда не удавалось воспроизвести эту ошибку, поэтому я решил написать скрипт, который ждет, пока ошибка не будет обнаружена, а затем interrupts GDB. Выгрузите стек и все релевантные переменные.

Пожалуйста, обратитесь к исходному вопросу C, чтобы узнать больше об ошибке

Вопрос

  1. Как создать динамическое прерывание? То есть, когда видна ошибочная строка, я должен отправить Ctrl+C, чтобы остановить процесс и получить контроль над подсказкой.
  2. Каков мой подход к поиску ошибки? Люди обычно используют такие методы тестирования? Не могли бы вы связать их?

Обновить

Ошибка была устранена путем замены функции sprintf на функцию, которая не работает с 64-битной средой (в 32-битной среде ARM см. этот вопрос) напрямую. Пожалуйста, перейдите к исходному вопросу, чтобы найти новую используемую функцию.


person clmno    schedule 06.09.2018    source источник
comment
о 2 : я обычно сначала пытаюсь воспроизвести, затем пытаюсь воспроизвести быстрее (больше, чем количество ошибок в день), затем в вашем случае, поскольку вы видите проблему снаружи, попробуйте найти способ наблюдать ее внутренне (может быть точка останова, но также может быть проверка условия в коде с помощью while(1), а затем запуск отладки без сброса). После этого вы почти закончили. Отладочная трассировка (если ваше устройство поддерживает ее) также является прекрасным (и захватывающим) инструментом.   -  person Julien    schedule 07.09.2018
comment
О 1: точка останова для каждого символа, который программа записывает в стандартный вывод (или канал, в который отправляется строка). Было бы лучше, если бы точка останова была на функции записи в программе с некоторой изменчивой переменной, используемой для запроса текущего записанного char в gdb. Затем напишите парсер для строки, если он обнаружит ошибочную строку, это ваша точка останова. О 2: Круто   -  person KamilCuk    schedule 08.09.2018
comment
Спасибо, парни. Я оставлю этот вопрос открытым, пока не найду решение. Я опубликую решение, как только найду его.   -  person clmno    schedule 08.09.2018