查找程序的bug

Java代码检查和bug分析工具 这里列出了3种Java静态分析工具,每一种工具关注一个特定的能发挥自己特长的领域,我们可以列举一下:   Java代码检查工具 PMD   Pmd 它是一个基于静态规则集的Java源码分析器,该软件功能强大,扫描效率高,是Java程序员debug的好帮手。   它可以识别出潜在的如下问题:   – 可能的bug——空的try/catch/finally/switch块。   – 无用代码(Dead code):无用的本地变量,方法参数和私有方法。   – 空的if/while语句。   – 过度复杂的表达式——不必要的if语句,本来可以用while循环但是却用了for循环。   立即下载

分享debug经验

1. 优先解决那些可重现的,可重现的bug特别好找,反复调试测试就好了,先把好解决的干掉,这样最节约时间。

2. 对于某些bug没有头绪或者现象古怪不知道从哪里下手,找有经验的同事问一下思路,因为在那种开发多年的大型系统里,经常会反复出现同样原因的bug,原因都类似,改了一处,过一阵子另外一处又冒出来,而且无法根治。
比如:我那个系统里有个特别危险的API,接口参数比较难用,一旦有人用错了某些情况下就会出诡异的现象,解决很简单,找到调用这个API的地方把调用方式写对就好了。为什么不根治呢?因为要保持兼容性不能改接口了。Windows系统里就好多这种烂API。
问下老员工吧,说不定他们都遇到过好多次了。

3. 放大现象,有些bug现象不太明显,那么就想办法增大它的破坏性,把现象放大。这只是个思路,具体怎么放大只能根据具体的代码来定。
比如:美剧《豪斯医生》里有一集,怀疑病人心肺有问题,就让病人去跑步机上跑步,加重心肺负担,从而放大症状。

4. 二分法定位,把程序逻辑一点点注释掉,看看还会不会出问题,类似二分查找的方法,逐步缩小问题范围。

5. 模拟现场,有时候我会问自己,如果我要实现bug描述的现象我要怎么写代码才行?
比如:我遇到一个死锁问题,但是检查代码发现所有的锁都是配对的,没有忘记解锁的地方,而且锁很简单就是一个普通的临界段,保护几行赋值语句而已。这样的代码怎么写才能让他死锁呢?
我想如果让我故意制造这样一个现象,只有在上锁的时候强制杀掉线程了。
既然这样就可以去看看有谁强杀线程了没有。

6. 制作工具,针对某些bug编写一些调试辅助工具。
比如,我那个系统没有完善的崩溃报告,虽然也有dump,但是分析出来的callstack经常不准。于是我为解决崩溃问题编写了个工具,会自动扫描代码,在每个函数入口和出口插入log,以此来定位崩溃点。

7. 掩盖问题,虽然这样做有点不厚道,但是有时不得不这么做。有些bug找不到真正的root cause,但是又要在规定时间内解决,那么我们就可以治疗症状而不去找病因。比如用try catch掩盖一些奇怪的崩溃。不到万不得已不要这么干,未来可能会付出更大代价。

我在做这份工作的时候也在追美剧《豪斯医生》,豪斯大叔解决病症的思路和debug差不多,对我很有启发。

Kenny Lang,热血软件工程师 / Googler:

同为刚毕业的新人,入职快6个月,非常理解楼主的问题。关于怎么找bug的问题,有人已经回答的很全面了。而且,其实最应该回答这个问题的应该是你的mentor。

首先,从bug入手,了解codebase,应该是平衡mentor和新人之间利益最大的办法。其实要想入手最快,就应该是让mentor24*7的在你旁边手把手教你,但这根本不现实,也没有意义。所以从修改bug入手,通过一个个小bug去了解整个project的结构和design pattern,对新人来说,这种学习既直观又不会被复杂的代码吓死。最主要的是,当你成功fix了一个bug,这种成就感是一个新入职的程序员勇往直前的动力。而且,修了一个bug,最重要的不是你unblock了多少人,或者帮助了多少用户,而是你从这个bug里看到了project怎么样的结构。当初为什么这么设计,为什么会出bug,时不时codebase里还有类似的bug,以后怎么避免。

别觉得不好意思去问你的mentor。他也许很忙,但他既然是你的mentor,就有义务帮助你平稳度过最开始的几个月,(而且,往往你的成功可以直接证明他的领导力强大)如果觉得过意不去,就多向你的老板/他的老板讲讲你们的事情。但是,一定要问有意义的问题。其实很多时候,如果你再多深入地看一页code,再多搜索一次别人写的wiki或者文档注释,就可以得到解答。这种问题,既浪费别人的时间,也不会让你养成深入思考和探索的习惯。久而久之,有事没事去问mentor就取代了你自己思考的过程。

mentor再牛,也不可能手把手的教你。但他可以教你的,是学习的方法/习惯、debug的方法/习惯、以及写code的方法/习惯。认真观察他的思路是怎么建立起来的,认真学习他是怎么debug的,认真看他是怎么涉及结构的。学会了,你也就出师了。

善用debug工具。不要小瞧debugging的过程。我真的见过已经是很成熟的程序员还在用二分法println debug。这不科学。。。尤其当你的project 变得很大,每次build就要好久,这样特别浪费时间。(尤其android)。设置break point和写有针对性的unit test必不可少。虽然又时候必须要看log,但有很多超级好用的debugger,稍微花时间去学习一下怎么用,或者看你的mentor怎么debug,会大大加快你的效率。(我曾经见过我的mentor用chrome debug。真的是觉得帅爆了!目瞪口呆”

其实新人很多时候都会觉得程序某个地方很“神奇”,明明应该这样,但却那样。千万不要跟你的mentor抱怨“神奇”,因为这两个字在整个代码行业就不存在。我的老板经常给我讲的一句话是,“code never lies”。代码运行异常,一定有运行异常的原因。不要揪着“为什么是这种异常”不放,而要去想“什么样的结果是对的”以及“怎么产生对的结果”。

学习framework。project变大了,framework必不可少。但因为framework的存在,让整个project变得更“捉摸不透”。所以,花点时间学学你们用得framework,以及针对这种framework debug的工具,静下心看看文档,自己在动手写一写,其实framework真的很美。

最后,时刻保持跟你mentor之间的sync up。让他知道你的困境,也让他知道你的成就。mentor也是从新人走过来的,没什么不能讲的。

我最绝望的时候是在入职两个礼拜。自己拿到了一些bug,也有了starting project。当时觉得自己对着电脑就像看着又大又丑的金刚。我也听说这个过程所有人都有,就算从别的公司跳过来、再资深的工程师,面对一个成熟的project,也都要花时间学习,经历失败、绝望。所以,没必要灰心,也没必要过度担心自己的表现。大家对新人的期待都很现实,所以稍微超出预期,就会得到很好的反馈。

Jitsi Meet保姆级自建教程:5分钟搞定私有化视频会议服务器(含Docker部署避坑指南) 本文提供了一份详尽的Jitsi Meet私有化视频会议服务器自建教程。通过Docker Compose部署方案,在5分钟内即可搭建基础服务,并深入解析了SSL/TLS证书配置、TURN服务器优化等关键步骤,确保部署的安全与可扩展性,为企业构建自主可控的远程协作平台提供完整指南。 阅读详情

相关推荐

机器视觉检测到底怎么做,经验分享

笔者做机器视觉检测已经有五六年了,也算是对机器视觉的检测技术有了一定的掌握。总的来说,基于机器视觉的检测技术主要包含三个部分:视觉采集模块、后台分析模块和动作决策模块。这几个分类,跟教科书上的有较大差异,很多同学觉得我在杜撰。笔者也不作反驳,因为这是笔者这些年工作经验的总结,自然区别于教科书。下面我们分开来讲这几个模块,同时会把笔者之前的论文做个推荐总结。 所有文章均可在博主的主页中找到,若无法找到,可以用搜索工具。博主的主页: https://blog.youkuaiyun.com/Aoulun 第..

Aoulun的博客 8678

各个阶段Bug数量估计

1.作测试计划的时候,是应该估计一下该软件的BUG数量,BUG集中点,以及修改该BUG的难度与时间 如果这些不估计,那编写测试用例的时候无法对某些重要模块作出着重测试 但是如何估计这个数量,那是任谁也帮不了你的,这得根据该团队的技术水平,以往项目测试的结果数据,本项目的系统分析报告及需求说明书来估计.而且这还不是想当然的去估计,是有公式的.但这套公式只有在历史数据最多的情况下预测出来的结果越准确.

CMM2CMMI的专栏 4698

智能车实战——从ADC采集到PWM控制,让电磁车精准循迹

本文详细介绍了电磁循迹智能车的实现原理与实战技巧,涵盖从ADC信号采集、PWM控制到PID算法整定的全流程。通过STM32代码示例解析电感信号处理、差比和偏差计算及电机驱动等关键技术,帮助开发者快速掌握智能车精准循迹的核心方法,提升电磁车竞赛项目的开发效率。

weixin_29192211的博客 301

程序员如何在复杂代码中查找到程序的bug?

最近在挑选更合适的物品来兑换,请牛牛们不要着急。 程序员新人怎样在复杂代码中找 bug? 姚冬,程序员: 我曾经做了两年大型软件的维护工作,那个项目有10多年了,大约3000万行以上的代码,参与过开发的有数千人,代码checkout出来有大约5个GB,而且bug特别多,open的有上千,即使最高优先级的showstopper也有上百。 分享下我的debug的经验 1.

走向架构师之路 3987

PWM(脉宽调制)技术详解:从基础到应用实践示例

PWM(脉宽调制)技术是嵌入式系统中一项重要的控制技术,通过调节脉冲宽度来实现对模拟设备的精准控制。从LED亮度到电机速度,PWM的应用场景非常广泛。对于嵌入式学习者来说,理解PWM的工作原理、掌握其配置方法,不仅能提升编程能力,还能为更多复杂系统的开发打下坚实的基础。

SpringWJN的博客 6329

【Matlab 六自由度机器人】基于改进型D-H参数的运动学建模与蒙特卡洛工作空间分析

本文详细介绍了如何使用改进型D-H参数法为六自由度机器人建立运动学模型,并利用Matlab Robotics Toolbox实现正运动学计算与可视化。通过蒙特卡洛法对机器人工作空间进行分析,生成三维点云图以直观展示其可达范围,为机器人选型与任务规划提供关键依据。

weixin_29040367的博客 439

新手程序员怎么在复杂的代码中寻找bug ?

首先,我们需要了解复杂代码中bug的成因。在实际工作中,程序员可以通过阅读代码、分析代码结构、审查代码变更等方式来识别潜在的bug。本文将探讨复杂代码中bug的成因与识别,以及如何在实践中运用调试工具、代码审查、静态分析、单元测试、集成测试、日志分析、调试策略等方法来提高新手程序员在复杂代码中寻找bug的能力。总之,新手程序员在面对复杂代码时,应掌握各种调试方法,善于利用调试工具和技巧,注重代码审查与静态分析,编写单元测试和集成测试,充分利用日志分析和调试策略,并在团队协作中不断学习、成长。

Q的博客 506

UE5 Paper2D性能优化:GroupedSpriteSceneProxy合批渲染原理与实践

在游戏开发中,渲染性能优化是核心技术挑战之一,其核心原理在于减少CPU与GPU之间的通信开销,特别是降低Draw Call数量。Draw Call是CPU向GPU提交绘制命令的指令,每次调用都涉及状态切换和数据传输,当场景中存在大量同质化对象时,频繁的Draw Call会成为主要性能瓶颈。为此,现代图形引擎普遍采用合批渲染技术,其技术价值在于将多个共享相同渲染状态(如材质、几何体)的物体数据合并提交,从而将多次Draw Call压缩为一次或少数几次,显著提升渲染效率。这一技术在2D游戏开发中尤为重要,例如在

weixin_34198453的博客 395

bug统计分析续(一)基于SQL的Bug统计方法

bug统计分析 基于SQL的Bug统计方法

lonelyrains的专栏 3366

Python-增加b站视频播放量

如果条件允许的情况下,有代理API更好,每次请求url调用API也更方便。如果没有的话,也不用担心,网上本身也有着很多免费国内代理,不过代理是否可用需要自己花点时间去检测,检测方法笔者这里就不详述了,后面有时间的话会单独针对这一块做详细说明。在开始之前,需准备代理IP。总之,在每次请求url的时候,随机带入某个IP防止被平台检测,便于达到增加播放量预期。大致思路就是针对你的目标代理平台进行IP抓取,并存入到自己本地的IP代理池。本文是该专栏的第1篇,后面会持续更新对应平台干货知识,记得关注。

Python进阶专栏《爬虫实战进阶》,《Pyppeteer从入门到精通》原创作者 5211

睿抗机器人魔力元宝在完成任务过程中如何使机械臂先到达白色盒子上方而不是先到达工作台?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1378

如何统计应用bug

1、看了下面这篇文章,你可以弄懂原理 【Android应用开发】 Android 崩溃日志 本地存储 与 远程保存 2、接入腾讯云分析,使用错误统计。

zhifanxu的专栏 744

QCC305x-QCC304x系列开发教程之应用程序子系统详解 嵌入式

本文对QCC305x-QCC304x系列芯片的应用程序子系统进行了详细解析,并给出了一个LED闪烁的示例代码。嵌入式系统的开发既需要理论知识的支持,也需要实践经验的积累,希望本文能够为读者在QCC305x-QCC304x系列芯片的开发中提供一些有益的指导。QCC305x-QCC304x系列芯片提供了丰富的外设接口,包括UART、SPI、I2C等,开发者可以根据需求选择适合的接口进行数据传输和控制。QCC305x-QCC304x系列芯片的应用程序子系统是整个嵌入式系统的核心部分,负责管理和执行各种应用程序。

CodeMaven的博客 226

90%程序员写不出无BUG的二分查找程序?

  90%程序员写不出无BUG的二分查找程序?相关文章链接如下:微软过桥问题与测试人员素养 等价类分法 新解 测试用例设计中的NP难题 测试驱动需求分析--需求文档评审实例 C/C++代码检视实例 《编程珠玑》(第二版)一书第四章中提及过100多名专业程序员使用两个小时的充足时间编写一个简单的二分查找程序,结果发现90%的人编出的代码都有BUG,Knuth也在他的《Sorting and Se

软件开发资料汇总 340

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Python如何查找程序中的bug

什么是bug 程序中出现的错误,但又没有通过异常去捕获,以至于直接抛出,导致程序的崩溃 bug一词的由来 bug 指的是小虫 飞入计算机中导致机器停止 打断点 也可使用print函数进行查找bug

Insane_Loafer的博客 713

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

simon106
博客等级 码龄9年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值