当前位置:网站首页>C#,入门教程——程序运行时的调试技巧与逻辑错误探针技术与源代码
C#,入门教程——程序运行时的调试技巧与逻辑错误探针技术与源代码
2022-07-28 06:20:00 【深度混淆】

一、关于程序错误的概述
编程的水平,如同人之体质,主要来自于基础,数学与算法;
但编程的功力,如同人的武功或运动成绩,则主要来自于调试、测试与跟踪。
程序的错误大致可分为:语法错误、数据错误、逻辑错误
我们都知道,如果程序在哪行?哪列出现语法错误,Visual Studio 编译器会直接指出来,一瞅便知,非常方便。
编译器首先就是为解决语法错误而设计的工具。
数据错误主要出现于局部,或 接口部分。局部性的数据错误,通过设置断点,然后按 F10, F11 等快捷键的单步调试是不错的办法。
但很多无法进行单步调试的 接口型数据错误,是比较麻烦的。只能用下面的办法。
逻辑错误是致命的、也是最难跟踪与分析的。逻辑错误还是过程性错误,往往要在程序运行时才会出现。可是,如果是编译通过的程序,称为运行时代码,出现错误,怎么知道哪行?哪列?哪个函数出现问题呢?
你可能阅读了很多这方面的文章,但就 C# 而言,建议你使用 北京联高软件开发有限公司 在这里开源的 Truffer 的基础类之一:C#运行时逻辑错误探针类。
特点:
(1)直接输出哪个源代码?行号?列号?函数名?重点信息;
(2)插入 探针 与 撤销 都非常简单;
(3)可 分页 输出超过 20 亿条的探针信息,只要你的硬盘空间足够富裕;
(4)基于输出的 探针信息,可以做很多的分析(大数据);
(5)基于下面代码的Truffer Xtracer功能更多,比如可以检测 死循环,可以探测堆、栈及重要数据的超界等。

二、逻辑错误探针类(简版)
#if DEBUG
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace Legalsoft.Truffer
{
public static class zz
{
private static StringBuilder sb { get; set; } = new StringBuilder();
private static string head { get; set; } = "";
private static string tail { get; set; } = "";
private static string format { get; set; } = "";
/// <summary>
/// 跟踪器的步数
/// </summary>
private static long step { get; set; } = 0;
/// <summary>
/// 每个 html 文件显示的 step 数
/// </summary>
private static long pagesize { get; set; } = 5000;
/// <summary>
/// 每隔 writesize 输出跟踪器语句(html)
/// 如果设置 writesize=0,则每个跟踪器语句都输出文件;
/// </summary>
private static long writesize { get; set; } = 100;
/// <summary>
/// 初始化
/// </summary>
private static void a()
{
if (head.Length == 0)
{
StringBuilder sx = new StringBuilder();
sx.AppendLine("<html>");
sx.AppendLine("<body>");
sx.AppendLine("<style>td { padding:5px;text-align:left; } </style>");
sx.AppendLine("<table width='100%' border=1 bordercolor='#AAAAEE' style='border-collapse:collapse;'>");
sx.Append("<tr style='background-color:#EEEEFF;'>");
sx.Append("<td>序号</td>");
sx.Append("<td>文件名</td>");
sx.Append("<td>行</td>");
sx.Append("<td>列</td>");
sx.Append("<td>函数名</td>");
sx.Append("<td>信息</td>");
sx.AppendLine("</tr>");
head = sx.ToString();
}
if (tail.Length == 0)
{
StringBuilder sx = new StringBuilder();
sx.Append("<tr style='background-color:#EEEEFF;'>");
sx.Append("<td>序号</td>");
sx.Append("<td>文件名</td>");
sx.Append("<td>行</td>");
sx.Append("<td>列</td>");
sx.Append("<td>函数名</td>");
sx.Append("<td>信息</td>");
sx.AppendLine("</tr>");
sx.AppendLine("</table>");
sx.AppendLine("</body>");
sx.AppendLine("</html>");
tail = sx.ToString();
}
if (format.Length == 0)
{
StringBuilder sx = new StringBuilder();
sx.Append("<tr>");
sx.Append("<td style='text-align:right'>{0}</td>");
sx.Append("<td>{1}</td>");
sx.Append("<td>{2}</td>");
sx.Append("<td>{3}</td>");
sx.Append("<td>{4}</td>");
sx.Append("<td>{5}</td>");
sx.AppendLine("</tr>");
format = sx.ToString();
}
}
/// <summary>
/// 探针函数
/// 调用方法为:
/// zz.z(new StackTrace(new StackFrame(true)).GetFrame(0));
/// </summary>
/// <param name="sf">堆栈帧</param>
/// <param name="info">你可以定义的任何类型的输出信息</param>
public static void z(StackFrame sf, string info = "")
{
a();
string buf = String.Format(format, step + 1, sf.GetFileName(), sf.GetFileLineNumber(), sf.GetFileColumnNumber(), sf.GetMethod().Name, info);
sb.AppendLine(buf);
if (step > 0)
{
if ((step % writesize) == 0 || writesize == 0)
{
string fn = String.Format("Z-{0:D8}.html", (int)((step - (step % pagesize)) / pagesize));
File.WriteAllText(fn, head + sb.ToString() + tail, Encoding.UTF8);
}
if ((step % pagesize) == 0)
{
sb.Clear();
sb.AppendLine(buf);
}
}
step++;
}
}
}
#endif
使用方法:
请将上面的代码保存为 Basic.Z.cs ,并加入 工程项目 project 即可。
三、探针类的使用
在原来的程序中加入适当的探针代码,然后运行程序即可输出 Z-0000000.html 这样的页面文件,可以直接用浏览器阅读,了解程序调用的顺序,并分析可能存在的逻辑问题。
1、探针插入
在需要记录(探测)的位置,插入下面这个语句:
#if DEBUG
zz.z(new StackTrace(new StackFrame(true)).GetFrame(0));
#endif
或者带重要信息(跟踪 begin end 的数据变化):
#if DEBUG
zz.z(new StackTrace(new StackFrame(true)).GetFrame(0), begin + ", " + end);
#endif
完整的代码示例:
...
using Legalsoft.Truffer;
namespace Legalsoft.DeepConfiser
{
public class TokenScanner
{
/// <summary>
/// 将全部令牌(tokens)
/// 按 {} 粗略划分到的层次型块(block)
/// (深度优先遍历的递归算法)
/// </summary>
/// <param name="parent"></param>
/// <param name="tokens"></param>
/// <param name="begin"></param>
/// <param name="end"></param>
public void Segmentation(Block parent, List<Token> tokens, int begin, int end)
{
#if DEBUG
zz.z(new StackTrace(new StackFrame(true)).GetFrame(0), begin + ", " + end);
#endif
if (tokens[begin].Buffer == "{" && tokens[end].Buffer == "}")
{
begin++;
end--;
}
...
}
}
}
2、探针的撤销

编译选项 #if DEBUG ,仅仅适用于调试模式的编译结果;对于 RELEASE 的编译版本而言,其中的 exe 文件是不含有 探针的,也不会输出 Z-00000000.html 文件,因而,一般来说,你无需刻意去删除(撤销)前面加入的探针代码。
小药治大病。
边栏推荐
- Tell you step by step what you need to do to apply for PMP? What should I do?
- JS thoroughly understand this point
- [chart component kit] Shanghai daoning provides developers with steema download, trial and tutorial
- There are two Kafka topics that need to write data intact to MySQL King through Flink. Scheme 1: write two f's
- Lecture notes a utility for everyone to generate PCG
- 非关系型数据库之Redis【Jedis客户端+Jedis连接集群】
- What if the computer file cannot be deleted?
- 【活动报名】云原生技术交流 Meetup,8 月 6 日广州见
- SQL function
- 非关系型数据库之Redis【redis安装】
猜你喜欢

网口网络水晶头RJ45、POE接口定义线序

Allure use
![Redis of non relational database [detailed setup of redis cluster]](/img/0b/bd05fb91d17f6e0dc9f657a4047ccb.png)
Redis of non relational database [detailed setup of redis cluster]

Will ordinary browsers disclose information? How to protect privacy by using a secure browser?

Prescan quick start to master the transportation elements in lesson 14, prescan

Meituan Er Mian: why does redis have sentinels?

"Wei Lai Cup" 2022 Niuke summer multi school training camp 2 supplementary question record (dghjkl)

Copper indium sulfide CuInSe2 quantum dots modified DNA (deoxyribonucleic acid) DNA cuinse2qds (Qiyue)

Understand CDN

EMC design strategy - clock
随机推荐
Rk3568 development board installation system startup
[dry goods] 32 EMC standard circuits are shared!
JS thoroughly understand this point
Can the variable modified by final be modified
Deep browser rendering principles
What if the task manager is not fully displayed?
Qt多线程中槽函数在哪个线程里执行分析
XSS knowledge points and 20 character short domain name bypass
DNA modified osmium OS nanoparticles osnps DNA modified iridium nanoparticles irnps DNA
js糖果消消乐小游戏源码
MPLS -- multi protocol label switching technology
Freezing and thawing of pytoch
DNA modified noble metal nanoparticles | DNA deoxyribonucleic acid modified metal palladium Pd nanoparticles pdnps DNA
Lecture notes a utility for everyone to generate PCG
@Documented 的作用
DNA deoxyribonucleic acid modified platinum nanoparticles ptnps DNA | scientific research reagent
【花书笔记】 之 Chapter01 引言
[leetcode] 24. Exchange nodes in the linked list in pairs
How to understand the adjective prefix of socket: "connection oriented" and "connectionless"
[chart component kit] Shanghai daoning provides developers with steema download, trial and tutorial