Memory leaks MonoTouch-WebRequest内存泄漏和崩溃?
我有一个MonoTouch应用程序,它使用3.5MB文件进行HTTP POST,在我测试的主要平台上(使用OS 3.1.2的iPhone 3G和使用OS 4.2.1的iPhone 4)非常不稳定。我会描述我在这里做什么,也许有人能告诉我我做错了什么 为了排除我应用程序的其他部分,我将其缩减为一个小样本应用程序。该应用程序是一个iPhone OpenGL项目,它只执行以下操作:Memory leaks MonoTouch-WebRequest内存泄漏和崩溃?,memory-leaks,xamarin.ios,webrequest,Memory Leaks,Xamarin.ios,Webrequest,我有一个MonoTouch应用程序,它使用3.5MB文件进行HTTP POST,在我测试的主要平台上(使用OS 3.1.2的iPhone 3G和使用OS 4.2.1的iPhone 4)非常不稳定。我会描述我在这里做什么,也许有人能告诉我我做错了什么 为了排除我应用程序的其他部分,我将其缩减为一个小样本应用程序。该应用程序是一个iPhone OpenGL项目,它只执行以下操作: 启动时,在30k块中分配6MB内存。这模拟了我的应用程序的内存使用情况 将3.5MB文件读入内存 创建一个线程来发布数据
- 仪器显示,随着应用程序继续上传,内存不会增加
- 仪器没有显示任何重大泄漏(可能总共1千字节)
- 无论我是以64k块编写post数据,还是使用一个Stream.write()调用一次性编写所有post数据
- 在开始下一次上传之前,我是否等待响应(HttpWebRequest.HaveResponse)并不重要
- POST数据是否有效并不重要。我尝试使用有效的POST数据,并尝试发送3MB的零
- 如果应用程序没有为每一帧分配任何数据,那么内存耗尽的时间会更长(但如前所述,我为每一帧分配的内存在其分配的帧之后不会被引用,因此GC应该将其占用)
using System;
using System.Net;
using System.Threading;
using System.Collections.Generic;
using System.IO;
using OpenTK.Platform.iPhoneOS;
using MonoTouch.CoreAnimation;
using OpenTK;
using OpenTK.Graphics.ES11;
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
using MonoTouch.OpenGLES;
namespace CrashTest
{
public partial class EAGLView : iPhoneOSGameView
{
[Export("layerClass")]
static Class LayerClass ()
{
return iPhoneOSGameView.GetLayerClass ();
}
[Export("initWithCoder:")]
public EAGLView (NSCoder coder) : base(coder)
{
LayerRetainsBacking = false;
LayerColorFormat = EAGLColorFormat.RGBA8;
ContextRenderingApi = EAGLRenderingAPI.OpenGLES1;
}
protected override void ConfigureLayer (CAEAGLLayer eaglLayer)
{
eaglLayer.Opaque = true;
}
protected override void OnRenderFrame (FrameEventArgs e)
{
SimulateAppAllocations();
UpdatePost();
base.OnRenderFrame (e);
float[] squareVertices = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
byte[] squareColors = { 255, 255, 0, 255, 0, 255, 255, 255, 0, 0,
0, 0, 255, 0, 255, 255 };
MakeCurrent ();
GL.Viewport (0, 0, Size.Width, Size.Height);
GL.MatrixMode (All.Projection);
GL.LoadIdentity ();
GL.Ortho (-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
GL.MatrixMode (All.Modelview);
GL.Rotate (3.0f, 0.0f, 0.0f, 1.0f);
GL.ClearColor (0.5f, 0.5f, 0.5f, 1.0f);
GL.Clear ((uint)All.ColorBufferBit);
GL.VertexPointer (2, All.Float, 0, squareVertices);
GL.EnableClientState (All.VertexArray);
GL.ColorPointer (4, All.UnsignedByte, 0, squareColors);
GL.EnableClientState (All.ColorArray);
GL.DrawArrays (All.TriangleStrip, 0, 4);
SwapBuffers ();
}
AsyncHttpPost m_Post;
int m_nPosts = 1;
byte[] LoadPostData()
{
// Just return 3MB of zeros. It doesn't matter whether this is valid POST data or not.
return new byte[1024 * 1024 * 3];
}
void UpdatePost()
{
if ( m_Post == null || m_Post.PostStatus != AsyncHttpPostStatus.InProgress )
{
System.Console.WriteLine( string.Format( "Starting post {0}", m_nPosts++ ) );
byte [] postData = LoadPostData();
m_Post = new AsyncHttpPost(
"https://api-video.facebook.com/restserver.php",
"multipart/form-data; boundary=" + "8cdbcdf18ab6640",
postData );
}
}
Random m_Random = new Random(0);
List< byte [] > m_Allocations;
List< byte[] > m_InitialAllocations;
void SimulateAppAllocations()
{
// First time through, allocate a bunch of data that the app would allocate.
if ( m_InitialAllocations == null )
{
m_InitialAllocations = new List<byte[]>();
int nInitialBytes = 6 * 1024 * 1024;
int nBlockSize = 30000;
for ( int nCurBytes = 0; nCurBytes < nInitialBytes; nCurBytes += nBlockSize )
{
m_InitialAllocations.Add( new byte[nBlockSize] );
}
}
m_Allocations = new List<byte[]>();
for ( int i=0; i < 10; i++ )
{
int nAllocationSize = m_Random.Next( 10000 ) + 10;
m_Allocations.Add( new byte[nAllocationSize] );
}
}
}
public enum AsyncHttpPostStatus
{
InProgress,
Success,
Fail
}
public class AsyncHttpPost
{
public AsyncHttpPost( string sURL, string sContentType, byte [] postData )
{
m_PostData = postData;
m_PostStatus = AsyncHttpPostStatus.InProgress;
m_sContentType = sContentType;
m_sURL = sURL;
//UploadThread();
m_UploadThread = new Thread( new ThreadStart( UploadThread ) );
m_UploadThread.Start();
}
void UploadThread()
{
using ( MonoTouch.Foundation.NSAutoreleasePool pool = new MonoTouch.Foundation.NSAutoreleasePool() )
{
try
{
HttpWebRequest request = WebRequest.Create( m_sURL ) as HttpWebRequest;
request.Method = "POST";
request.ContentType = m_sContentType;
request.ContentLength = m_PostData.Length;
// Write the post data.
using ( Stream stream = request.GetRequestStream() )
{
stream.Write( m_PostData, 0, m_PostData.Length );
stream.Close();
}
System.Console.WriteLine( "Finished!" );
// We're done with the data now. Let it be garbage collected.
m_PostData = null;
// Finished!
m_PostStatus = AsyncHttpPostStatus.Success;
}
catch ( System.Exception e )
{
System.Console.WriteLine( "Error in AsyncHttpPost.UploadThread:\n" + e.Message );
m_PostStatus = AsyncHttpPostStatus.Fail;
}
}
}
public AsyncHttpPostStatus PostStatus
{
get
{
return m_PostStatus;
}
}
Thread m_UploadThread;
// Queued to be handled in the main thread.
byte [] m_PostData;
AsyncHttpPostStatus m_PostStatus;
string m_sContentType;
string m_sURL;
}
}
使用系统;
Net系统;
使用系统线程;
使用System.Collections.Generic;
使用System.IO;
使用OpenTK.Platform.iPhoneOS;
使用MonoTouch.core动画;
使用OpenTK;
使用OpenTK.Graphics.ES11;
使用单调的基础;
使用MonoTouch.objc运行时;
使用MonoTouch.OpenGLES;
命名空间崩溃测试
{
公共部分类EAGLView:iPhoneOSGameView
{
[导出(“层类”)]
静态类LayerClass()
{
返回iPhoneOSGameView.GetLayerClass();
}
[导出(“initWithCoder:”)]
公共EAGLView(NSCoder编码器):基本(编码器)
{
LAYERTAINSBACKING=错误;
LayerColorFormat=EAGLColorFormat.RGBA8;
ContextRenderingApi=EAGLRenderingAPI.OpenGLES1;
}
受保护的覆盖无效配置层(CaeAglayer eAglayer)
{
eaglLayer.不透明=真;
}
RenderFrame上受保护的覆盖无效(FrameEventArgs e)
{
模拟位置();
UpdatePost();
基于渲染帧(e);
浮动[]平方顶点={-0.5f,-0.5f,0.5f,-0.5f,-0.5f,0.5f,0.5f,0.5f,0.5f};
字节[]squareColor={255,255,0,255,0,255,255,255,0,0,
0, 0, 255, 0, 255, 255 };
MakeCurrent();
总图视口(0,0,大小。宽度,大小。高度);
GL.MatrixMode(所有投影);
GL.LoadIdentity();
GL.正交(-1.0f,1.0f,-1.5f,1.5f,-1.0f,1.0f);
GL.MatrixMode(All.Modelview);
GL.旋转(3.0f、0.0f、0.0f、1.0f);
GL.ClearColor(0.5f、0.5f、0.5f、1.0f);
总帐清除((uint)全部彩色缓冲位);
GL.VertexPointer(2,全部浮点,0,平方顶点);
GL.EnableClientState(所有VertexArray);
GL.ColorPointer(4,All.UnsignedByte,0,squareColors);
GL.EnableClientState(All.ColorArray);
GL.DrawArray(All.TriangleStrip,0,4);
天鹅垫();
}
异步HttpPost m_Post;
int m_nPosts=1;
字节[]LoadPostData()
{
//只需返回3MB的零。这是否是有效的POST数据并不重要。
返回新字节[1024*1024*3];
}
void UpdatePost()
{
if(m|u Post==null | m|u Post.PostStatus!=AsyncHttpPostStatus.InProgress)
{
System.Console.WriteLine(string.Format(“起始post{0}”,m_nPosts++));
字节[]postData=LoadPostData();
m_Post=新的AsyncHttpPost(
"https://api-video.facebook.com/restserver.php",
“多部分/表单数据;边界=“+”8cdbcdf18ab6640”,
postData);
}
}
随机m_Random=新随机(0);
列出m_分配;
列表m_初始分配;
void simulateAppLocations()
{
//第一次,分配应用程序将分配的一组数据。
如果(m_InitialAllocations==null)
{
m_InitialAllocations=新列表();
整数九字节=6*1024*1024;
int nBlockSize=30000;
对于(int nCurBytes=0;nCurBytesbyte[] buffer = new buffer[1024];
int bytesRead = 0;
using (FileStream fileStream = File.OpenRead("YourFile.txt"))
{
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
httpPostStream.Write(buffer, 0, bytesRead);
}
}