Войти
ФлеймФорумПрограммирование

C#. Ссылка на элемент массива.

Страницы: 1 2 3 4 Следующая »
#0
1:50, 13 янв. 2020

Подскажите, почему этот код корректно работает? Как он получает доступ к несуществующему элементу массива?

using System;
using static System.Console;

class Program
{
    static void Main()
    {
        var arr = new[] {1, 2, 3};
        ref var x = ref arr[2];
        WriteLine(x); // 3
        x = 10;
        Array.Resize(ref arr, 1);
        WriteLine(arr.Length); // 1
        WriteLine(x); // 10 !!!
    }
}

#1
(Правка: 2:32) 2:31, 13 янв. 2020

Скорее всего, это всё волшебный сборщик мусора.

#2
(Правка: 3:51) 3:44, 13 янв. 2020

У массивов в .NET фиксированная длина. Массив до «изменения размера» и массив после «изменения размера» ― это два совершенно разных массива:

internal static void Resize<T>(ref T[] array, int length, int newSize)
{
  if (newSize < 0)
  {
    throw new ArgumentOutOfRangeException();
  }

  if (array == null)
  {
    array = new T[newSize];
    return;
  }

  if (array.Length == newSize)
  {
    return;
  }

  T[] array2 = new T[newSize];
  Array.Copy(array, array2, Math.Min(newSize, length));
  array = array2;
}
#3
10:03, 13 янв. 2020

Delfigamer
Можно подумать на крестах будет по другому.

#4
11:24, 13 янв. 2020

Dampire
> Можно подумать на крестах будет по другому.
Ну как тебе сказать... фраза "всё будет совершенно по-другому" не даст даже малейшего представления, насколько по-другому в крестах обстоят дела.

#5
11:40, 13 янв. 2020

Delfigamer
Такая же программа на крестах выполнится с совершенно идентичным результатом.

#6
(Правка: 12:15) 12:10, 13 янв. 2020

Dampire
> Такая же программа на крестах выполнится с совершенно идентичным результатом.
Нет.
Результат выполнения аналогичной программы на крестах - это может произойти всё что угодно; иногда звёзды совпадают так, что это "что угодно" оказывается внешне идентичным с результатом решётки; иногда они совпадают так, что всё сразу и очень громко взрывается (чего я специально добился в примере выше); но чаще всего результатом оказываются никак не связанные с проблемным кодом баги, возникающие через 10 лет после его написания.

#7
12:21, 13 янв. 2020

Delfigamer
> > Такая же программа на крестах выполнится с совершенно идентичным
> > результатом.
> Нет.

std::function<int()> intr(int i)
Ткни пальцем в код в первопосте где были бы функции возвращающие функции... А то меня смущает "такая же программа" в комментарии выше.
#8
12:26, 13 янв. 2020

В Delphi еще точно такая же лабуда, причём за счёт ref-counting-а слабать очень похожий пример, но с гарантируемым поведением очень просто. Просто вторую ссылку надо не на элемент запоминать, а на сам массив, а потом "удивляться" почему в отресайзенном элементы уже другие.
Классика.

#9
12:35, 13 янв. 2020

Delfigamer
Прекрати, зелень. Реаллокация с указателем на старый участок памяти работает везде одинаково и за один майн никто в эту память ничего не запишет.

#10
12:37, 13 янв. 2020

=A=L=X=
> Ткни пальцем в код в первопосте где были бы функции возвращающие функции... А
> то меня смущает "такая же программа" в комментарии выше.
https://dotnetfiddle.net/fxElmf так лучше?
Или ты относишься к тем, что считает, что UB не существует, пока его не станет видно?

#11
12:50, 13 янв. 2020

Delfigamer
> Или ты относишься к тем, что считает
Что если сказали "привести аналогичный пример", то надо приводить аналогичный, а не говорить вообще невесть что и зачем придуманное.

#12
12:50, 13 янв. 2020

PhotoMaster19
> но на практике никто уже на этом не пишет.

Пишут, но скрывают.

#13
(Правка: 12:57) 12:54, 13 янв. 2020

В дельфи на раз делается без всяких UB:

SetLength( arr1, 10 );
arr2 := arr1;
SetLength( arr1, 20 );
arr2[ x ] := ???; // А элементы то другие

То что в примере ссылка на элемент, а не на массив конечно немного другое, но объясняется конечно же тем что шарпы в ссылке на элемент массива запоминают просто ссылку на массив, иначе бы сборщик мусора отвалился.

P.S.

Интересно, что только часа два назад модифицировал одну из своих программ для работы на Delphi под способность не удалять файлы справа между синхронизируемыми "каталогами".
Но много на эту тему я действительно не распространяюсь.

#14
14:05, 13 янв. 2020

Group99
>Как он получает доступ к несуществующему элементу массива?
Никто не получает доступ ни к какому элементу массива. Произошло примерно следующее.
Ты записал в переменную конкретный адрес (адрес 3 элемента массива), затем поместил по этому адресу число 10, ресайз массива пометил этот адрес как «мусор» и сказал, что туда, в общем-то, теперь можно записывать что угодно.
Затем ты взял из переменной тот же самый адрес и прочитал то, что в нем лежит (мусор). А лежит в нем по-прежнему 10, т.к. никто другой ничего туда ещё не записал.

Поправьте, если в решетках работает иначе.

Страницы: 1 2 3 4 Следующая »
ФлеймФорумПрограммирование