WPF应用程序内存泄漏的一些原因

原文:Finding Memory Leaks in WPF-based applications

There are numbers of blogs that folks wrote about memory leaks in Microsoft .Net Framework managed code and unmanaged code based applications.

 

In this blog I wanted to:



    • Show coding practices that can cause memory leaks which are more unique to WPF-base apps


    • Share information about memory leaks in the .NET Framework;


    • Show how to avoid these leaks


  • Discuss the tools and techniques available to detect the leaks


I plan to update this blog with more code samples as we continue to investigate customers’ applications and find additional platform leaks or coding practices that cause memory leaks in WPF-based applications.


The Sample


To illustrate the issues I attached a sample application. The application can launch different child windows; each can cause a separate memory leak. In each of the cases, closing the child window does not actually release the memory held by Window object as you would expect.


image


For clarity, I’ve included a table of the leaks:


Leak Description


Developer Error


NETFX 3.0


NETFX 3.5


NETFX 3/5 sp1


Improper Use of Event Handlers


X


 


 


 


Improper Use of Data Binding


X


 


 


 


Improper Use of Command Binding


X


X


X


X


Improper Use of Static Event Handlers


X


 


 


 


Use BitmapImage in ImageSource


 


X


X


 


Multiple Use of BitmapImage


 


 


X


 


Use of downloaded BitmapImage


 


X


 


 


CMilChannel leaks if initial HWND destroyed on XP


 


X (XP only)


X (XP only)


X (XP only)


ShutdownListener leaked for each thread using Binding


 


X


X


X


Create and Destroy WriteableBitmap on XP in HW


 


 


 


X (XP in HW Only)


SW Viewport 3D w/ VisualBrush, WB, etc. leaks on XP

   

X (XP in HW Only)


The Leak


To see the leak:



    1. On Windows Vista, launch Process Explorer.  Open the process property dialog for your app (Right-Click/Properties)

 

    1. Launch few of the Child windows. 

 

    1. Notice memory grows by ~50MB on each launch.

 

    1. Close a dialog without checking the checkbox (e.g. “Clear events on Close to avoid memory Leak”.)

 

    1. Click of “Force GC” to force garbage collection.

 

    1. Notice memory is not re-claimed

 

  1. Repeat (4)+(5) , but now check each of the Checkbox.  This will free the objects being held when window closes. Notice in Process Explorer that memory is now reclaimed.

 

clip_image004


Each of the child windows causes a leak because of the reasons below.


1. Use of Event Handler


image


Figure 1-Leak caused by use of Event Handler



Cause:



This leak is triggered because the child window (Window2) has a reference (it registered to an event) to Window1 TextBox1 which remains alive causing the Window2 object and its element tree to remain alive.


In general, if you do this:

        Foo.SomeEvent += new EventHandler(Bar.SomeMethod)  




Then when you done using Bar, but you are still using Foo then Bar will still remain alive as well. Not what you might have expected.



Code:


Window1.w1.TextBox1.TextChanged += new TextChangedEventHandler(this.TextBox1_TextChanged);

 

 

The Window2 object will remains “alive” as long as TextBox1 in Windows1 remain alive.



The Fix/Workaround:



There are couple of approaches, the easiest one is simply to un-register the Windows2 object from its various event sources when the windows is about to close.



e.g.:

Window1.w1.TextBox1.TextChanged -= new TextChangedEventHandler(TextBox1_TextChanged);

 

 



The second approach is to create some sort of indirections (e.g. “Weak references”). See this Greg Schechter's blog for an example.


2. Use of Data Binding


image


Figure 2 - Leak caused by use of Data Binding



Cause:



This leak documented in this kb article. It is triggered because:


The TextBlock control has a binding to an object (myGrid) that has a reference back to the TextBlock (it is one of myGrid children’s).


Note that this type of a DataBinding leak is unique to a specific scenario (and not to all DataBinding scenarios) as documented in the kb article.  The property in the Path is a not a DependencyProperty and not on a class which implements INotifyPropertyChanged and in addition a chain of strong reverences must exist.



Code:


myDataBinding = new Binding("Children.Count");
myDataBinding.Source = myGrid;
myDataBinding.Mode = BindingMode.OneWay;
MyTextBlock.SetBinding(TextBlock.TextProperty, myDataBinding);

 

 

 

 



Same leaky code can be also written in XAML:


   <TextBlock Name="MyTextBlock" Text="{Binding ElementName=myGrid, Path=Children.Count}" />

 

 

 

Fix/Workaround:



There are few of approaches, the easiest one is simply to clear the binding when the windows is about to close.


e.g.:

      BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);

 

 

Other approach is to set the mode of the data binding to OneTime. See the kb article for other ideas.


3. Use of Command Binding


image


Figure 3 - Leak caused by use of Command Binding



Cause:



This leak triggered because Window2 object adds a command binding to Window 1.


WPF Command Binding uses strong reference which causes the Windows2 object child window not be released as long as Windows2 remain alive.



Code:


command = new RoutedCommand("ClearBox", this.GetType());
command.InputGestures.Add(new KeyGesture(Key.F5));
myCmdBinding = new CommandBinding(command, F5CommandExecute);
Window1.w1.CommandBindings.Add(myCmdBinding); //add binding to Window 1

 

 

 

 



Note: This is likely not a common code practice, but it is provided to demonstrate the idea certain usage of Command Binding can cause leaks.



Fix/Workaround:



The easiest approach is simply to clear the CommandBinding when the windows is about to close.



E.g.:


    Window1.w1.CommandBindings.Remove(myCmdBinding); 

 

 

 

4. Use of Static Event Handler


image


Figure 4 - Leak caused by use of Command Binding



Cause:



This leak is triggered because the child window (Window2) has a reference (it registered to an event) to a Static event. Since object is static, Windows2 object will never get released.



Code:


Application.Current.Activated += new EventHandler(App_Activated);




The Fix/Workaround:



Simply un-register the Windows2 object from the event sources when the windows is about to close.


e.g.:

    Application.Current.Activated -= new EventHandler(App_Activated);

 

 

The second approach is to create You can consider other approaches like (1) from before.


5. Use of BitmapImage in Image Source


image


Figure 5 - Leak caused by use of BitmapImage as Image Source



Cause:



This leak is triggered because under the covers WPF keeps a strong reference between the static BitmapImage (bi1) and the Image (m_Image1).


BitmapImage (bi1) is declared Static so it is not Garbage Collected when Window2 is closed, since under the covers WPF hooks events on the BitmapImage (for example the DownloadFailed event) it causes the m_Image1 Image to remain alive.


This in turn causes the entire Window2 tree to also remain alive in memory even after you closed it.


This leak can happen only when you use BitmapImage. It does not appear when you use DrawingImage for example.


This issue is fixed in the next .Net service pack (.Net 3.5 Sp1)



Code:



bi1 =     //bi1 is static
  new BitmapImage(new Uri("Bitmap1.bmp",UriKind.RelativeOrAbsolute));
//bi1.Freeze() //if you do not Freeze, your app will leak memory 
m_Image1 = new Image();
m_Image1.Source = bi1;  
MyStackPanel.Children.Add(m_Image1); 

 

 

 





The Fix/Workaround:



Workaround can depends on your sceanrio. One workaround would be to Freeze the BitmapImage.


WPF does not hook events for objects that are frozen.


This woraround is used if you click on the 2nd checkbox above. Another workaround could be to Clone the BitmapImage or not to make it Static.


In general you should Freeze objects whenever possible to improve the performance of your application and reduces its working set. Read more here.


E.g.:

bi1.Freeze();

 

6. Use of BitmapImage in Image Source (Multiple Use)



image


Figure 6 - Leak caused by use of BitmapImage as Image Source (multiple use)



Cause:



This leak is related to the leak mentioned above.


This leak is triggered because under the covers WPF keeps a strong reference between the static BitmapImage (bi1) and the Image (m_Image1).


When the Image gets assigned a new source (e.g. m_Image1.Source = bi2;), WPF “forgot” to remove the previous “old” events it hooked under the covers for bi1.


Again, since bi1 is static and is not Garbage Collected, it forces the Image to remain alive which causes the entire Windw2 to leak.


This issue was introduced in .Net 3.5. It does not exist in .Net 3.0.


It is fixed in the next .Net service pack (.Net 3.5 Sp1)


 



Code:



static BitmapImage bi1 = 
   new BitmapImage(new Uri("Bitmap1.bmp", UriKind.RelativeOrAbsolute));
static BitmapImage bi2 =
   new BitmapImage(new Uri("Bitmap2.bmp", UriKind.RelativeOrAbsolute));

if (bi2.CanFreeze)
bi2.Freeze();
//bi1.Freeze() //even though you are really using bi2 for Image Source, you also need to Freeze bi1 it to avoid leak  
m_Image1 = new Image();
m_Image1.Source = bi1; // use un-frozen bitmap, which causes the leak
m_Image1.Source = bi2; // use frozen bitmap
MyStackPanel.Children.Add(m_Image1);

 

 


 

 

 

 





The Fix/Workaround:



The workaround is simply not use the code above or also Freeze the other BitmapImage e.g.: bi1.Freeze();


7. Use of downloaded BitmapImage in Image Source



image


Figure 7 - Leak caused by use of downloaded BitmapImage as Image Source



Cause:



This leak is triggered because WPF does not remove internal reference to certain objects (such as LateBoundBitmapDecoder, BitmapFrameDecode, etc) which are used during web download and causes the leak.


This leak only happens when you download an image from the internet. (E.g. it does not appear when you load images from your local machine)


This issue will get fixed in the next .net service pack (.Net 3.5 Sp1)


To see the leak, you can launch above window, close it, and click on the ‘Force GC’ button to force garbage collection.


When you run the below commands in WinDbg, you will notice among others the following objects that remain in the heap. These are the objects that cause the leak and hold on to the Image control and the entire tree after you closed the Window2.


.loadby sos mscorwks
!DumpHeap -type System.Windows.Media.Imaging
 
53dadf18   6   72 System.Windows.Media.UniqueEventHelper`1
    [[System.Windows.Media.Imaging.DownloadProgressEventArgs, PresentationCore]]
53da4374   1  108 System.Windows.Media.Imaging.PngBitmapDecoder
53da09e0   4  112 System.Windows.Media.Imaging.BitmapSourceSafeMILHandle
53d8d2f0   1  120 System.Windows.Media.Imaging.LateBoundBitmapDecoder
53da0524   1  172 System.Windows.Media.Imaging.BitmapFrameDecode
53da89c8   3  648 System.Windows.Media.Imaging.BitmapImage

 

 

 


 



Code:



// You will see leak when using BitmapImage loaded from the Internet
BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(@http://www.somesite.com/some_image.png,
                          UriKind.RelativeOrAbsolute);
image.CacheOption = BitmapCacheOption.OnLoad;
image.CreateOptions = BitmapCreateOptions.None;
image.EndInit();

 

m_Image1 = new Image();
m_Image1.Source = image;
MyStackPanel.Children.Add(m_Image1);


 

 

 


 

 

 

 





The Fix/Workaround:



The workaround is to consider downloading the BitmapImage first in other means to a temporary folder or to memory and then use the local BitmapImage . (See WebClient.DownloadFile & WebClient.DownloadData APIs)


 


8. CMilChannel leaks if initial HWND is destroyed on XP



clip_image001



Cause:



This is a leak in WPF present in versions of the framework up to and including .NET 3.5 SP1. This occurs because of the way WPF selects which HWND to use to send messages from the render thread to the UI thread. This sample destroys the first HWND created and starts an animation in a new Window. This causes messages sent from the render thread to pile up without being processed, effectively leaking memory.



The Fix/Workaround:



The workaround is to create a new HwndSource first thing in your App class constructor. This MUST be created before any other HWND is created by WPF. Simply by creating this HwndSource, WPF will use this to send messages from the render thread to the UI thread. This assures all messages will be processed, and that none will leak. 
Note: This issue is rare; only implement the workaround if you’re actually hitting this problem.


9. ShutDownListener leaked for every thread created using Binding



Cause:



This is a leak in WPF present in versions of the framework up to and including .NET 3.5 SP1. This occurs because an event handler in WPF’s data binding engine is hooked but never unhooked whenever binding is used on a new thread. This sample creates a number of new Threads, and for each creates a new Window using data binding.



The Fix/Workaround:



None Available


10. Create and destroy WriteableBitmap on XP in hardware rendering



clip_image002



Cause:



This is a leak in WPF present in version 3.5 SP1 ONLY. This occurs whenever a WriteableBitmap is created and destroyed on Windows XP using hardware rendering. This sample repeatedly creates, updates, and displays new WriteableBitmaps continuously to leak memory.



The Fix/Workaround:



Force software rendering for the Window containing the WriteableBitmap by setting HwndTarget.RenderMode to RenderMode.SoftwareOnly.


11. Viewport3D w/ VisualBrush, WriteableBitmap, etc, leaks in Windows XP in SW



clip_image003 
Cause:



This is a leak in WPF present in version 3.5 SP1 ONLY. This occurs when a VisualBrush, WriteableBitmap, or some select other classes are used within a Viewport3D in software rendering mode.



The Fix/Workaround:



If available, use HW rendering. If HW rendering is not available, and you suspect that you’re hitting this leak, try replacing your brush with a SolidColorBrush to see if the leak goes away. If the leak persists, you have another leak in your application. If the leak goes away consider using a different brush that does not leak; no other workaround is available.


Debugging the leak


To experiment with finding the leak I used both CLR Profiler for the .NET Framework 2.0 and WinDbg and both seem adequate. The advantage is that both are free downloads.


Useful tips:


I found that:




    1. It is much easier to detect a leak if you purposely make it very large. E.g. add 50MB to the size of the objects that you suspect to be leaking.  In my example I am allocating ~50MB of memory in each child window (byte[]).

 


    1. If you only have a small leak it may require many iterations before you can conclude that leak exists when using Process Explorer or Task Manger.

 


    1. Forcing Garbage Collector to reclaim memory helps to differentiate between objects that leak and the ones that don’t. This code should do it:

                   GC.Collect();
      GC.WaitForPendingFinalizers();
      GC.Collect();


 


  1. Forcing the GC is useful when you visually inspect memory (e.g. using Process Explorer), if you use the CLR Profiler it already force GC between each heap snapshot.

 

Using CLR Profiler



    1. Launch the CLR Memory Profiler as admin on Vista

 

    1. Uncheck “Allocations”, “Calls” & “Profiling Active” checkboxes

 

    1. Do “Start Application” and get the app to the point where you ready to take the ‘before’ heap snapshot.

 

    1. Then click “Show Heap Now”

 

    1. Now check the “Profiling Active” & “Allocations” to enable profiling.

 

    1. Launch  and then close the ‘leaky’ window (e.g. “Event Handler test”)

 

    1. Take another “Show Heap Now”.

 

  1. Right-click on the last graph and “Show New Objects”.

 

          image



You can see that my TextChangedEventHandler is holding on to 50MB of Byte[], as in image below:


image


Repeating the process for the “Command Binding test” window, shows the 50MB of CommandBinding object. See image:


image


Using WinDBG



Pretty much followed the directions provided in this blog here.


windbg -p <your process id>


0:004> .loadby sos mscorwks


I performed:


0:005> !DumpHeap –stat


Twice (before and after the leak)


“!DumpHeap –stat” showed this before the leak happened:



5695e56c      460        18400 System.Windows.DependencyProperty


5696975c      188        20280 System.Windows.EffectiveValueEntry[]


79135df4       99        34440 System.Reflection.CustomAttributeNamedParameter[]


0056ed60      297        37656      Free


7913b600      177        65376 System.Collections.Hashtable+bucket[]


7912b884     3307       152020 System.Object[]


790fc6cc     8516       455296 System.String


Total 32362 objects


After the leak “!DumpHeap –stat” showed this :


5543b1e8      189        11340 System.Windows.Markup.BamlAttributeInfoRecord


53d0d3ac       40        11424 System.Windows.ClassHandlers[]


569698f4      384        11888 MS.Utility.FrugalMapBase+Entry[]


790febbc      627        12540 System.RuntimeType


5695e7c0      628        12560 System.Windows.DependencyProperty+FromNameKey


5696975c      244        15928 System.Windows.EffectiveValueEntry[]


5542d18c      676        16224 System.Windows.FrameworkPropertyMetadata


5695e56c      484        19360 System.Windows.DependencyProperty


7913b600       80        38952 System.Collections.Hashtable+bucket[]


7912b884      785        73608 System.Object[]


0056ed60      288       103380      Free


790fc6cc     7218       373856 System.String


7913b858       57     52433700 System.Byte[]


A ‘suspicions’ allocation of 50MB of byte[] is shown


I then performed:


0:005> !dumpheap -type System.Byte[]



013894d4 7913b858       60    


0138965c 7913b858      228    


013897c0 7913b858       60    


01389a70 7913b858       60    


0138f6d4 7913b858      500    


06dc1000 7913b858 52428816    


total 57 objects


Statistics:


      MT    Count    TotalSize Class Name


7913b858       57     52433700 System.Byte[]


Total 57 objects


I then performed gcroot on the largest allocation and windbg reported


0:005> !gcroot 06dc1000


Note: Roots found on stacks may be false positives. Run "!help gcroot" for


more info.


Scan Thread 0 OSTHread 1280


ESP:37f2d8:Root:012f6d68(System.Windows.Threading.Dispatcher)->


0130c6b0(System.Windows.Input.InputManager)->


0130cd58(System.Windows.Input.StylusLogic)->


0130ce8c(System.Collections.Generic.Dictionary`2[[System.Object, mscorlib],[System.Windows.Input.PenContexts, PresentationCore]])->


0130ced8(System.Collections.Generic.Dictionary`2+Entry[[System.Object, mscorlib],[System.Windows.Input.PenContexts, PresentationCore]][])->


0135e1e8(System.Windows.Interop.HwndSource)->


012fab4c(TestWpfApp.Window1)->


01334b90(System.Windows.Controls.TextBox)->


0136f664(System.Windows.EffectiveValueEntry[])->


0134deb0(System.Windows.EventHandlersStore)->


01383340(MS.Utility.ThreeObjectMap)->


01383320(MS.Utility.FrugalObjectList`1[[System.Windows.RoutedEventHandlerInfo, PresentationCore]])->


0138332c(MS.Utility.SingleItemList`1[[System.Windows.RoutedEventHandlerInfo, PresentationCore]])->


01383300(System.Windows.Controls.TextChangedEventHandler)->


0137e2d8(TestWpfApp.Window2)->


06dc1000(System.Byte[])


Scan Thread 2 OSTHread 1500


DOMAIN(005656C8):HANDLE(WeakSh):c1794:Root:01384aec(System.EventHandler)->


01384828(System.Windows.Documents.AdornerLayer)->


0137e2d8(TestWpfApp.Window2)


This is pretty much the same info that the CLR memory Profiler reported.


Other tools



There are other third-party memory profilers such as SciTech’s Memory Profiler , Red-Gate’s ANTS Profiler , YourKit ProfilerJetBrains dotTrace 3.0 and others. All provide nice and richer user interface and better support than the tools I used above.


Other types of leaks



There are other types of managed memory leaks but outside the scope of this blog.


One such typical leak is when a managed object is holding onto unmanaged resources.


This can occur when:


a) Managed objects that hold on to the unmanaged resources and do not clean-up after themselves as they suppose to (typically in theIDisposable implementation).


b) Very small managed object that holds onto a large amount of unmanaged memory. The garbage collector sees only small amount of managed memory and does not realize that collection is required. This scenario is typically common with bitmaps since bitmaps have a small managed component holding on to a large size of unmanaged memory.


This scenario is improved in .Net 2.0 with the introduction of the AddMemoryPressure API which allows objects to tell the garbage collector of the unmanaged allocation size.


WPF internally already forces garbage collection, so the recommendation to consider using the AddMemoryPressure API is only if you have a similar scenario in your own app.


Summary



In all the patterns above, the underlying issue is the usage of strong references to objects that remain alive. Some of these strong references are implemented by the underlying WPF Framework; however the concept of strong reference used by event handler is not new in WPF and existed since the first version of .Net Framework and Winform.


Memory leaks are potentially more evident in WPF because of some new programming concepts WPF exposes and the internal WPF implementation. In addition, a typical WPF application is much richer in graphics and media, so if the app does leak memory, the leak is typically of a significant size and is easily noticeable. This makes it more important for app developers to be careful and avoid leaks in their apps.


Useful resources



    • Ian Griffiths' blog entry: "Simulating Weak Delegates for EventHandler-like Delegates"


    • Greg Schechter’s Simulating “Weak Delegates” in the CLR


    • Rico Mariani's Performance Tidbits


    • CLR Profiler for the .NET Framework 2.0


    • WinDbg


  • Third-party memory profilers: SciTech’s Memory Profiler , Red-Gate’s ANTS Profiler , YourKit ProfilerJetBrains dotTrace 3.0 and others which I have not listed.



Special thanks to Adam Smith, Eric Harding and Momin Al-Ghosien who helped in review and Mike Cook who contributed to this blog.

转载于:https://www.cnblogs.com/144823836yj/p/8675077.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[转]Eclipse RCP应用系统开发方法与实战2-- 定制应用程序窗口属性

5.1.4 定制应用程序窗口属性 向导生成的应用程序主界面并不能满足要求&#xff0c;存在很多问题&#xff0c;例如&#xff0c;主界面运行时没有自动居中&#xff0c;主界面大小没有固 定&#xff0c;主窗口标题栏文字应该是“高校经费测算系统”。再看看图5-3、图5-4的标题栏有…

赢在中国 - 史玉柱经典语录

1.要重视建立销售手册2.凡是先做试点&#xff0c;风险才低。3.找到自己的细分市场。4.不要总想着同竞争对手对立&#xff0c;而是要想办法让自己弥补竞争对手的不足。5. 如果没有价格上的优势与技术上的绝对优势&#xff0c;千万不要进入红海市场&#xff0c;否则你会必输无疑&…

我最近在学微信小程序开发,一起吗?

从当初的一夜成名&#xff0c;到今天火爆的市场占有率&#xff0c;微信小程序已走过 4 个年头。据今年 1 月阿拉丁发布的报告显示&#xff0c;微信小程序 2020 年 DAU 已破 4 亿&#xff0c;其总数超 380 万。最近有读者问我说&#xff0c;发哥&#xff0c;之前自己一直是个人…

WebService大讲堂之Axis2(2):复合类型数据的传递

在实际的应用中&#xff0c;不仅需要使用WebService来传递简单类型的数据&#xff0c;有时也需要传递更复杂的数据&#xff0c;这些数据可以被称为复合类型的数据。数组与类&#xff08;接口&#xff09;是比较常用的复合类型。在Axis2中可以直接使用将WebService方法的参数或返…

Linux虚拟摄像头vivid配置

总述最近在看摄像头驱动&#xff0c;需要配置虚拟摄像头的驱动&#xff0c;但是教程里面是linux2.6内核的&#xff0c;实际电脑的是Ubuntu16&#xff0c;内核是linux4.15版本&#xff0c;从2.6到4.15内核好多文件发生了变化&#xff0c;所以我们该怎么操作呢&#xff1f;下面就…

第一次工作报告

要求 1. 对源文件&#xff08;*.txt,*.cpp,*.h,*.cs,*.html,*.js,*.java,*.py,*.php等&#xff09;统计字符数、单词数、行数、词频&#xff0c;统计结果以指定格式输出到默认文件中&#xff0c;以及其他扩展功能&#xff0c;并能够快速地处理多个文件。 2. 使用性能…

树莓派Pico的一些有趣的基本实验

▲ 实验电路板Raspberry PI Pico小型MCU模块&#xff0c;以其价格低廉&#xff0c;功能丰富&#xff0c;开发方便为很多非电子类专业的同学进行创意项目原型设计提供了方便的平台。下面的一些实验给CDIE课程设计同学们制作的一些基本演示实验。▌01 PI Pico实验板在 RASPBERRY …

Gabor变换

gabor变换分析非平稳信号有弊端主要是时频窗宽度固定 小波wavelet a小窗窄a大窗宽 窗口或短时傅氏变换在时域上和频域上的局部化程度主要由窗函数g(x)的有效时宽Δt 和有效带宽Δf 决定。Δt 和Δf 越小, 表明局部性越好。但Heisenberg 测不准原理指出[ 6] :Δt 和Δf 不可能任…

30块钱的树莓派跑unix系统,源码全部开源,香

▌ 1、前言之前做活动抽奖送的几个树莓派&#xff0c;但是因为好几个人都没有填写地址&#xff0c;所以就只能把东西寄回来给我&#xff0c;然后手痒自己玩了下&#xff0c;觉得这个东西确实很香&#xff0c;比一般的Linux开发板都好。PICO这个开发板可以玩很多东西1 、运行pic…

为什么大家都只谈薪资,却不谈梦想?

说个薪资的问题&#xff0c;最近在帮一个朋友物色工作&#xff0c;当然&#xff0c;除了我那个朋友以外&#xff0c;也有挺多同学向我咨询offer薪资的问题。先说我那个朋友。高中毕业后去当兵&#xff0c;服兵役结束后去4s店修车&#xff0c;我车子的很多问题也会向他咨询&…

差生的 8 年程序员总结

今年终于从大菊花厂离职了&#xff0c;离职前收入大概60w不到吧&#xff0c;在某乎属于比较差的&#xff0c;今天终于有空写一下自己的职场故事&#xff0c;也算是给自己近8年的程序员工作做个总结复盘。近8年有些事情做对了&#xff0c;也有更多事情做错了&#xff0c;在这里记…

Python简单的抓取静态网页内容

import requests from bs4 import BeautifulSoup res requests.get(http://news.sina.com.cn/china/)#获取目标网页 res.encoding utf-8#抓取网页出现乱码 #print(res.text) soup BeautifulSoup(res.text,html.parser)#爬取网页 for news in soup.select(.news-item): if le…

直观感受电路信号波形:半波整流电路

前言电子电路的理论很抽象&#xff0c;所以多看电子电路的信号波形&#xff0c;对掌握理论知识非常有帮助。让我们通过形象的电路信号波形&#xff0c;直观地了解电路的世界&#xff01;半波整流电路半波整流电路&#xff0c;电路图很简单&#xff0c;通过一个二极管实现半波整…

【nodejs】安装browser-sync 遇到错误提示

首先我用的是mac电脑在我执行安装browser-sync时遇到如下问题&#xff1a; 因为不被允许所以我只能不安装全局了&#xff1a; 但是又出现了如下的新问题 纠结了半个小时&#xff0c;终于知道为什么会出现这个问题了&#xff0c; node只有--global or -g才是全局安装的包&#x…

本机获取Intel AMT IP地址的例子

转自&#xff1a;http://software.intel.com/zh-cn/blogs/2009/02/10/intel-amt-ip/?cidsw:51cto Intel AMT的IP地址设置有两种模式&#xff1a;静态IP和动态IP。 在动态IP&#xff0c;也就是DHCP自动分配的情况下&#xff0c;本机的操作系统起来后&#xff0c;Intel AMT的I…

如何解密单片机内程序?

▌单片机解密是什么&#xff1f;单片机解密又叫单片机破解&#xff0c;芯片解密&#xff0c;IC解密&#xff0c;但是这严格说来这几种称呼都不科学&#xff0c;但已经成 了习惯叫法&#xff0c;我们把CPLD解密&#xff0c;DSP解密都习惯称为单片机解密。单片机只是能装载程序芯…

拆解玩具电池充电器:充久了可能会爆,廉价电路方案让人震惊!

▲ 本文要分析的电路家里有不少给小孩子买的电动玩具&#xff0c;感叹现在的电动玩具虽然才几十块钱&#xff0c;但是不仅包邮&#xff0c;还附送充电器和可充电电池&#xff0c;真的很便宜&#xff0c;大家都买得起。下图这款充电器忘了是哪个玩具附送的&#xff0c;看起来像模…

炒股从负债百万,到“睡后收入”上百万,我做了这件事!

问你一个很残酷的问题&#xff1a;你炒股到现在&#xff0c;赚钱了吗&#xff1f;因为股市里永远存在着“7亏2平1赢”的规律。如果你想要在市场里保持持续的盈利状态&#xff0c;你就得成为其中的“1”&#xff0c;而不是7和2&#xff01;也就是说&#xff0c;想要在市场里立足…

I/O流总结

一,I/O流概述I/O流简单的理解就是数据的输入与输出;那数据的的输入与输出又怎么理解呢?首先我们知道,所有的数据在计算机中都是以二进制的形式存储的.我们看到的字节或者字符形式的文件都是计算机经过解析之后形成的.那么数据的输入与输出简单地说,就是我们向计算机(通信设备)…