Search Unity

Where is my memory leak?

Discussion in 'Scripting' started by eco_bach, Nov 29, 2015.

  1. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    After just a few minutes my app crashes. I assume the issue is in the following script. If, as I think, the issue is in the LateUpdate method where I create a new Texture2D and new Rect object, how do I accomodate changing screen sizes (this is a standalone application)?


    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class ReadPixelsReduced : MonoBehaviour {
    6.  
    7. private int _sW;
    8. private int _sH;
    9.  
    10. float originX;
    11. float originY;
    12.  
    13. [SerializeField]
    14. int width=32;
    15. [SerializeField]
    16. int height=28;
    17.  
    18. Rect rect;
    19. Rect testRect;
    20. Texture2D texture;
    21.  
    22. private Texture2D test_Texture;
    23.  
    24.  
    25. float [] greyscaleVals = new float [32*18];
    26.  
    27.     // Use this for initialization
    28.     void Start () {
    29.     }
    30.  
    31.  
    32.  
    33.     void LateUpdate(){
    34.         _sW=Screen.width;
    35.         _sH=Screen.height;
    36.  
    37.         originX = 0.5f * _sW - (.5f * width);
    38.         originY = 0.5f * _sH - (.5f * height);
    39.  
    40.         rect = new Rect(originX,originY, width, height);
    41.         texture = new Texture2D(_sW,_sH,TextureFormat.RGB24,false);
    42.     }
    43.  
    44.  
    45.     void OnPostRender(){
    46.     }
    47.  
    48.  
    49.     void OnRenderImage (RenderTexture source, RenderTexture destination)
    50.     {
    51.  
    52.     texture.ReadPixels(rect,0,0,false);
    53.          texture.Apply();
    54.      
    55.         Graphics.Blit (source, destination);
    56. int x, y = -1;
    57. for (int i = 0; i < 32 * 18; i++) {
    58.      x = i % 32;
    59.      greyscaleVals = texture.GetPixel(x, x == 0 ? ++y : y).grayscale;
    60. }
    61.     Debug.Log("ASSERT OnRenderImage greyscaleVals.Length ] = "+greyscaleVals.Length+"\n");
    62.     Debug.Log("ASSERT OnRenderImage greyscaleVals.Length[0][1] = "+greyscaleVals[300]+"\n");
    63.     }
    64.  
    65.  
    66.     void OnGUI () {
    67.  
    68.     }
    69.  
    70.  
    71. }
    72.  
     
    Last edited: Nov 29, 2015
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,539
    Use code tags, please:
    http://forum.unity3d.com/threads/using-code-tags-properly.143875/

    Also, why are you creating a new Texture2D EVERY update?

    I could see having to if you want to match the screen resolution exactly... but in that case only create a new texture IF and ONLY IF the screen has actually changed in size.

    And if you're going to be replacing a Texture with another Texture, as with any unmanaged object (Texture2D is the managed mono object that represents the unmanaged data on the unity side of things), you need to manually destroy it by calling Object.Destroy(...).

    The same way you would with a Component, GameObject, or other unity Object.
     
    Last edited: Nov 29, 2015
    eco_bach likes this.
  3. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    Thanks. Added CODE tags. Moved new Texture2D to my Start method. Do you know if creating a new Rect every frame could also potentially cause memory issues?
     
  4. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    I think creating a new rect would not cause any memory issues, since im pretty sure Rect is a value type that is on the Stack.
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,539
    Rect is a struct, so it's a value type. It is not an unmanaged unity object type, so you don't have the leaking issues with that. You'll know if it's a unity if it inherits from UnityEngine.Object.

    Being a value type doesn't necessarily mean it'll be on the stack.

    In this instance, because said rect is a class member field, it'll exist as part of the memory that is allocated when you instantiate that class. Which is on the heap.

    Structs being "on the stack" is that when used as a temporary value in a short scope (a scope of code that closes soon, like a function, if statement, for loop, etc) a value will be placed on the stack. Where as an object created in this scope will be on the heap, and the pointer to it on the stack.