1

Can someone help me and suggest how to resolve or handle this OutOfMemoryException?

The task for addMany is to add a sequence of numbers after the index. For example, if we use it to add 10, 20 and 30, starting from the third position in a list containing 1 2 3 4 5 6 7 8, the list will look like this: 1 2 3 10 20 30 4 5 6 7 8.

It throws only with this input:

1 2 3 4 5 6 7 8

push 9

push 21

pop

shift

addMany 3 10 20 30

remove 5

print

This is my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _2comandi
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> arr = Console.ReadLine().Split(' ').Select(int.Parse).ToList();
            List<int> copy = new List<int>();
            List<int> copy1 = new List<int>();
            string[] commands = Console.ReadLine().Split(' ').ToArray();
            string command = commands[0];
            while (command != "print") {
                switch (command)
                {
                    case "push":
                        arr.Add(int.Parse(commands[1]));
                        break;
                    case "pop":
                        Console.WriteLine(arr[arr.Count-1]);
                        arr.Remove(arr[arr.Count-1]);
                        break;
                    case "shift":
                        copy.Add(arr.Count);
                        for (int i = 0; i < arr.Count - 1; i++) 
                        {
                            copy.Add(arr[i]);
                        }
                        arr = copy;
                        break;
                    case "addMany":
                        int command1 = int.Parse(commands[1]);
                        if (command1 <= arr.Count)
                        {
                            for (int i = 0; i < arr.Count; i++)
                            {
                                if (command1 == i)
                                {
                                    for(int j = 2; j<commands.Length; j++)
                                    {
                                        copy.Add(int.Parse(commands[j]));
                                    }
                                    copy.Add(arr[i]);
                                }
                                else
                                {
                                    copy.Add(arr[i]);
                                }
                            }
                        }
                        arr = copy;
                        break;
                    case "remove":
                        int command11 = int.Parse(commands[1]);
                        if (command11 <= arr.Count)
                        {
                            arr.Remove(arr[command11]);
                        }
                        break;
                    case "print":break;
                }
                commands = Console.ReadLine().Split(' ').ToArray();
                command = commands[0];
            }
            arr.Reverse();
            Console.WriteLine(String.Join(", ", arr));

        }
    }
}
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
trakiiskasalata
  • 51
  • 1
  • 1
  • 5

1 Answers1

4

addMany 3 10 20 30

This is the command causing the exception. First of all, when you make this assignment

arr = copy;

You are not copying by value but by reference, as usually happens with a couple of List.

In other words, you don't have two different "containers" with the same values, but two "pointers" to the same "container" of values.

If you make a change to arr, you change copy too and vice versa, since they actually point to the same "container" of values.

So, when you enter this loop:

    for (int i = 0; i < arr.Count; i++)
    {
        if (command1 == i)
        {
            for (int j = 2; j < commands.Length; j++)
            {
                copy.Add(int.Parse(commands[j]));
            }
            copy.Add(arr[i]);
        }
        else
        {
            copy.Add(arr[i]);
        }
    }

And you add something to copy, like here

copy.Add(arr[i]);

you are actively adding to arr to, incrementing arr.Count, which is the exit condition of your for loop.

So you are never going out of you for loop because for each iteration... you also move up the exit condition.

And, you know, infinite loops fill your memory, causing the exception to be thrown.

Just to add more details, if you want to copy one List into another, you need a so called deep copy, while so far you have a shallow copy.

In your case, a deep copy between your lists is as simple as adding ToList():

arr = copy.ToList();

Be aware that this is not always safe; in your case it works because your lists contain integers, i.e. value types. If you want to be completely sure and avoid bad surprises, before your for loop calculate the exit condition, save it in an integer and use that as exit condition:

int ExitCount = arr.Count();
for (int i = 0; i < ExitCount; i++)
Francesco B.
  • 2,729
  • 4
  • 25
  • 37