31 / 21 / 10
Регистрация: 08.10.2017
Сообщений: 181
1

Исключение NullReferenceException

07.07.2019, 22:56. Показов 1449. Ответов 17

Author24 — интернет-сервис помощи студентам
Добрый вечер! Всю голову сломал, не могу понять ошибку.
Каждый раз при попытке присвоить значение ячейке массива вылетает NullReferenceException (показано во вложении), и непонятно, почему это происходит. Массив инициализирован, у каждой из переменных есть своё значение. в чем может быть проблема?
Миниатюры
Исключение NullReferenceException  
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.07.2019, 22:56
Ответы с готовыми решениями:

Класс Masif - исключение NullReferenceException
Есть класс Масив: using System; using System.Collections.Generic; using System.Linq; using...

Чтение из BinaryWriter. Исключение NullReferenceException
Создайте файл, содержащий записи о студентах из 3 групп (не менее 15). name - string; group - ...

При отладке выскакивает исключение NullReferenceException
При отладке выскакивает исключение NullReferenceException в строке if() (даже при if(4 == 4) или...

Непонятно из-за чего выбрасывается исключение NullReferenceException
Вот фрагмент кода for (int i=0;i<massive1.Length; i++){ string x; ...

17
4 / 3 / 1
Регистрация: 07.11.2016
Сообщений: 36
07.07.2019, 23:04 2
Было бы легче вам помочь если бы вы скинули весь код.
Не понятно чему равняется ваша переменная tmp?
0
31 / 21 / 10
Регистрация: 08.10.2017
Сообщений: 181
07.07.2019, 23:06  [ТС] 3
Совсем забыл про код, следующий до этого:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Thread
    {
        public int[] sign;
        public int n, p, depth;
        public string[] trans;
        public int[] _i, _j;
        public long det = 0;
        public int[,] matrix2; 
        public string[,] indexes; 
 
        public void Start_Det(int tmp)
        {
            depth = 0;
            trans[depth] = indexes[tmp, depth];
            _i[depth] = tmp;
            _j[depth] = depth;
            depth++;
            Det_Count();
        }
}
До этого этот класс вызывается из другого следующим образом:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class Main
    {
        Thread[] thr;
        public int[,] matrix2; 
        public string[,] indexes; 
        public int[] sign; 
        public int n, p;
        public long det;
        Stopwatch tmr = new Stopwatch();
        public string Det_Count(string _sign)
        {
            int tmp = 0;
            sign = new int[_sign.Length];
            for (int i = 0; i < _sign.Length; i++)
                sign[i] = Convert.ToInt32(_sign[i].ToString());
            int[] _i = new int[n];
            int[] _j = new int[n];
            thr = new Thread[(int)Math.Pow(n, p - 1)];
            Task[] tasks = new Task[(int)Math.Pow(n, p - 1)];
            for (int i=0; i<(int)Math.Pow(n, p-1);i++)
            {
                thr[i] = new Thread();
                thr[i].n = n;
                thr[i].p = p;
                thr[i]._i = _i;
                thr[i]._j = _j;
                thr[i].sign = sign;
                thr[i].indexes = indexes;
                thr[i].matrix2 = matrix2;
            }
            tmr.Restart();
            for (int j = 0; j < (int)Math.Pow(n, p - 1); j++)
            {
                tmp = j;
                tasks[j] = Task.Factory.StartNew(() =>
                {
                    try
                    {
                        thr[tmp].Start_Det(tmp);
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.Message);
                    }
                }
                );
            }
            Task.WaitAll(tasks);
            return tmr.Elapsed.ToString();
        }
}
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
07.07.2019, 23:25 4
Цитата Сообщение от Slepoyi Посмотреть сообщение
Массив инициализирован
Массив trans у Вас где инициализируется? Я что то не нашел этого в Вашем коде...
1
4 / 3 / 1
Регистрация: 07.11.2016
Сообщений: 36
07.07.2019, 23:33 5
У вас стринговой переменной indexes не присвоено значения (ну или я слеп), а string - это ссылочный тип переменных, и если ей не присвоить значение она по умолчанию принимает значение null

Добавлено через 2 минуты
trans он пытается инициализировать с помощью indexes но он пуст)))
1
31 / 21 / 10
Регистрация: 08.10.2017
Сообщений: 181
07.07.2019, 23:56  [ТС] 6
Да, действительно, как-то прозевал этот момент и даже не инициализировал массив. Странно, что компилятор выделил следующую за ошибочной строку и ругался на неё. Но его уже заметил и исправил, а теперь совсем впал в ступор.
Во вложении скриншот: массив 64x4, на нём вылетает исключение в виде ухода за границы. И теперь непонятно: почему при допустимых значениях переменных может случиться вылет?
Миниатюры
Исключение NullReferenceException   Исключение NullReferenceException   Исключение NullReferenceException  

0
4 / 3 / 1
Регистрация: 07.11.2016
Сообщений: 36
08.07.2019, 00:17 7
А каковы границы цикла?
Чему равно pow(n, p-1)?
0
31 / 21 / 10
Регистрация: 08.10.2017
Сообщений: 181
08.07.2019, 00:28  [ТС] 8
My3oH4ik, массив задан [pow(n, p-1), n], что в данной задаче 64 и 4 соответственно, границы цикла от 0 до pow(n, p-1), что тоже в пределах допустимого.
C#
1
indexes = new string[(int)Math.Pow(n, p - 1), n];
0
4 / 3 / 1
Регистрация: 07.11.2016
Сообщений: 36
08.07.2019, 00:42 9
Из этой части кода который вы предоставили, сложно понять где и что не так. В части кода которые на скриншотах, вроде все хорошо, но это только потому, что мы не видим значения многих переменных, и то что выполняет например функция Candidate
Но если для вас это какой то супер секретный код, и вы не можете его предоставить для проверки, то может вам поспать? Отдохнуть, и может когда отдохните сами увидите ошибку?
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
08.07.2019, 06:20 10
Цитата Сообщение от My3oH4ik Посмотреть сообщение
trans он пытается инициализировать с помощью indexes
Где??? Если речь о строке
C#
1
trans[depth] = indexes[tmp, depth];
так это он пытается присвоить элементу с индексом depth какое то значение из indexes (который, как Вы верно заметили, также пустой)... А сам массив trans то он нигде не создает... Объявил и сразу пытается использовать.
0
31 / 21 / 10
Регистрация: 08.10.2017
Сообщений: 181
08.07.2019, 19:50  [ТС] 11
asn31337, My3oH4ik, я, наверное, не очень хорошо поступил, выкидывая код кусками, а не целиком и спрашивая совета.
Вот код основного класса:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
 
namespace Newest_Det
{
    class Main
    {
        Thread[] thr;
        public int[,] matrix2; // матрица 2
        public string[,] indexes; // матрица индексов
        public int[] sign; //сигнатура по номерам индексов
        public int n, p;
        public long det;
        public int ex_counter = 0;
        Stopwatch tmr = new Stopwatch();
        public string Det_Count(string _sign)
        {
            int tmp = 0;
            sign = new int[_sign.Length];
            for (int i = 0; i < _sign.Length; i++)
                sign[i] = Convert.ToInt32(_sign[i].ToString());
            int[] _i = new int[n];
            int[] _j = new int[n];
            thr = new Thread[(int)Math.Pow(n, p - 1)];
            Task[] tasks = new Task[(int)Math.Pow(n, p - 1)];
            for (int i=0; i<(int)Math.Pow(n, p-1);i++)
            {
                thr[i] = new Thread();
                thr[i].n = n;
                thr[i].p = p;
                thr[i].sign = sign;
                thr[i].indexes = indexes;
                thr[i].matrix2 = matrix2;
            }
            tmr.Restart();
            for (int j = 0; j < (int)Math.Pow(n, p - 1); j++)
            {
                tmp = j;
                tasks[j] = Task.Factory.StartNew(() =>
                {
                    //thr[tmp].Start_Det(tmp);
                    try
                    {
                        thr[tmp].Start_Det(tmp);
                    }
                    catch (Exception e)
                    {
                        ex_counter++;
                        //MessageBox.Show(e.Message);
                    }
                }
                );
            }
            Task.WaitAll(tasks);
            return tmr.Elapsed.ToString();
        }
        public void Init(string _n, string _p)
        {
            n = Int32.Parse(_n);
            p = Int32.Parse(_p);
            Random Rand = new Random();
            matrix2 = new int[(int)Math.Pow(n, p - 1), n];
            for (int j = 0; j < n; j++)
                for (int i = 0; i < (int)Math.Pow(n, p - 1); i++)
                    matrix2[i, j] = Rand.Next(-10, 10);
            indexes = new string[(int)Math.Pow(n, p - 1), n];
            if (n == 2 || n == 4 || n == 8)
                Parallel.For(0, n, Fill);
            else
                Parallel.For(0, n, Else_Fill);
        }
        public void Fill(int _tmp)
        {
            int c = _tmp * (int)Math.Pow(n, p - 1);
            int fc = c;
            string res = "";
            if (n == 2 || n == 4 || n == 8)
                switch (n)
                {
                    case 2:
                        for (int i = 0; i < (int)Math.Pow(n, p - 1); i++)
                        {
                            for (int j = 0; j < p; j++)
                            {
                                res = (fc & 1).ToString() + res;
                                fc = fc >> 1;
                            }
                            indexes[i, _tmp] = res;
                            res = "";
                            c = c + 1;
                            fc = c;
                        }
 
                        break;
                    case 4:
                        for (int i = 0; i < (int)Math.Pow(n, p - 1); i++)
                        {
                            for (int j = 0; j < p; j++)
                            {
                                res = (fc & 3).ToString() + res;
                                fc = fc >> 2;
                            }
                            indexes[i, _tmp] = res;
                            res = "";
                            c = c + 1;
                            fc = c;
                        }
                        break;
                    case 8:
                        for (int i = 0; i < (int)Math.Pow(n, p - 1); i++)
                        {
                            for (int j = 0; j < p; j++)
                            {
                                res = (fc & 7).ToString() + res;
                                fc = fc >> 3;
                            }
                            indexes[i, _tmp] = res;
                            res = "";
                            c = c + 1;
                            fc = c;
                        }
                        break;
                }
        }
        public void Else_Fill(int i)
        {
            string res = "";
            int[] num = new int[p];
            int[] one = new int[p];
            one[0] = 1;
            int dsum;
            int rp = 0;
            num[num.Length - 1] = i;
            for (int j = 0; j < (int)Math.Pow(n, p - 1); j++)
            {
                for (int l = num.Length - 1; l >= 0; l--)
                {
                    res = res + num[l];
                }
                indexes[j, i] = res;
                res = "";
                for (int k = 0; k < p; k++)
                {
                    dsum = (num[k] + one[k] + rp);
                    num[k] = dsum % n;
                    rp = (dsum) / n;
                }
                num[num.Length - 1] += rp;
            }
        }
        public void Init_From_file(string _fn)
        {
            StreamReader Mat = new StreamReader(_fn);
            p = Convert.ToInt32(Mat.ReadLine());
            n = Convert.ToInt32(Mat.ReadLine());
            matrix2 = new int[(int)Math.Pow(n, p - 1), n];
            for (int j = 0; j < n; j++)
                for (int i = 0; i < (int)Math.Pow(n, p - 1); i++)
                    matrix2[i, j] = Convert.ToInt32(Mat.ReadLine());
            indexes = new string[(int)Math.Pow(n, p - 1), n];
            if (n == 2 || n == 4 || n == 8)
                Parallel.For(0, n, Fill);
            else
                Parallel.For(0, n, Else_Fill);
        }
        public long Det()
        {
            for (int i = 0; i < (int)Math.Pow(n, p - 1); i++)
                det = det + thr[i].Get_Det();
            return det;
        }
        public int Ex()
        {
            return ex_counter;
        }
    }
}
Вот код вызываемого класса:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
using System;
 
namespace Newest_Det
{
    class Thread
    {
        //Main main = new Main();
        public int[] sign;
        public int n, p, depth;
        private string[] trans;
        private int[] _i, _j;
        public long det = 0;
        public int[,] matrix2; // может это можно убрать??
        public string[,] indexes; // и это
 
        public void Start_Det(int tmp)
        {
            trans = new string[n];
            _i = new int[n];
            _j = new int[n];
            depth = 0;
            //trans[depth] = main.indexes[tmp, depth];
            trans[depth] = indexes[tmp, depth];
            _i[depth] = tmp;
            _j[depth] = depth;
            depth++;
            Det_Count();
        }
        public void Det_Count()
        {
            if (depth > 0)
            {
                if (depth == n) // если построена трансверсаль
                {
                    int det_part = 1;
                    for (int i = 0; i < trans.Length; i++)
                    {
                        det_part = det_part * matrix2[_i[i], _j[i]];
                    }
                    det = det + det_part * Sign();
                    depth--;
                    trans[depth] = null;
                }
                else // если трансверсали нет
                {
                    for (int i = 0; i < Math.Pow(n, p - 1); i++)// в цикле смотрим трансверсальные элементы
                    {
                        if (Candidate(indexes[i, depth]) == true)
                        {
                            trans[depth] = indexes[i, depth];
                            _i[depth] = i;
                            _j[depth] = depth;
                            depth++;
                            Det_Count();
                        }
                    }
                    depth--;
                    trans[depth] = null;
                }
            }
        }
        public int Sign()
        {
            int h; // вспомогательный индекс
            string tmp;
            int znak = -1;
            int inv = 0;
            int[,] perestan = new int[n, p];
            if (sign.Length == 1) //перманент
            {
                znak = (int)Math.Pow(znak, 2);
            }
            else//trans[n]
            {
                for (int i = 0; i < n; i++)
                {
                    tmp = trans[i];
                    for (int j = 0; j < p; j++)
                    {
                        perestan[i, j] = Convert.ToInt32(tmp[j].ToString()); //задали матрицу индексов для подсчета инверсий
                    }
                }
                tmp = "";
                for (int i = 0; i < sign.Length; i++)
                {
                    h = -1;
                    for (int j = 0; j < trans.Length; j++)
                    {
                        h = h + 1;
                        for (int k = h; k < trans.Length; k++)
                        {
                            if (perestan[k, sign[i]] < perestan[j, sign[i]])
                                inv++;
                        }
                    }
                }
                znak = (int)Math.Pow(znak, inv);
            }
            return znak;
        }
        public bool Candidate(string _cand)
        {
            string tmp = "";
            bool res = true;
            for (int i = 0; i < trans.Length; i++)
            {
                if (trans[i] != null && res != false)
                {
                    tmp = trans[i];
                    for (int j = 0; j < _cand.Length; j++)
                    {
                        if (_cand[j] == tmp[j])
                            res = false;
                    }
                }
            }
            return res;
        }
        public long Get_Det()
        {
            return det;
        }
    }
}
Массив indexes заполняется в Fill или Else_Fill, также заполняются matrix2 и sign, затем создаётся массив классов Thread и они должны параллельно отрабатывать на заданной с помощью tmp части массива indexes.
Если просто запустить программу, то она отрабатывает неправильно, выкидывая кучу исключений (всегда разное количество, что было выяснено значением ex_counter). Если поставить точку останова на 41 строке класса Main, там где
C#
1
tmr.Restart();
и выполнять программу, нажимая f11 (через шаг с заходом надеялся попасть внутрь класса Thread и посмотреть, что он у себя делает, но не вышло), тогда программа отработает без исключений и выдаст правильный результат. В чем может быть дело? Я неправильно сконструировал создание и запуск потоков или дело в чем то еще?
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
09.07.2019, 13:18 12
Slepoyi, наверное, будет проще, если Вы выложите тут проект целиком, чтобы можно было скачать и запустить у себя. А то, если честно, очень лень разбираться в коде и пытаться найти причину)))
0
31 / 21 / 10
Регистрация: 08.10.2017
Сообщений: 181
12.07.2019, 17:12  [ТС] 13
asn31337, https://drive.google.com/file/... sp=sharing, залил на диск. Чтобы работал, вводите в n и р числа от 2 до 6, в текстбокс сигнатуры лучше ввести "01", нажать Инит и затем Дет.
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
14.07.2019, 12:54 14
Цитата Сообщение от Slepoyi Посмотреть сообщение
Чтобы работал, вводите в n и р числа от 2 до 6, в текстбокс сигнатуры лучше ввести "01", нажать Инит и затем Дет.
Попробовал... Вроде, все нормально работает... Что то считает))) Не знаю насколько корректен результат, но, по крайней мере, с указанными Вами параметрами, исключений не возникает.
Исключение NullReferenceException
1
31 / 21 / 10
Регистрация: 08.10.2017
Сообщений: 181
14.07.2019, 13:54  [ТС] 15
asn31337, блин, вот тут третье число (которое 212) - это количество исключений. Там в классе Main если конструкцию try-catch закомментировать, то исключения будут видны явно.
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
14.07.2019, 16:49 16
Цитата Сообщение от Slepoyi Посмотреть сообщение
Там в классе Main если конструкцию try-catch закомментировать, то исключения будут видны явно.
Аааа! ))) Я код не смотрел))) Просто запустил, смотрю - работает)))

Добавлено через 9 минут
А исключение возникает по такой причине:
Вот тут:
C#
1
2
3
4
5
6
7
8
9
        public void Start_Det(string[,] _indexes, int[,] _matrix2, int tmp)
        {
            ...
            trans = new string[n];
            ...
            depth = 0;
            trans[depth] = indexes[tmp, depth];
            ...
        }
создается массив trans. В этот момент все его n элементов равны null. Далее первому (и только) элементу присваивается значение из массива indexes. При этом все остальные элементы остаются равны null. И далее Вы перебираете все элементы этого массива:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
        public int Sign()
        {
            ...
                for (i = 0; i < n; i++)
                {
                    tmp = trans[i];
                    for (j = 0; j < p; j++)
                    {
                        perestan[i, j] = Convert.ToInt32(tmp[j].ToString()); // вот тут при n>0 и будет исключение
                                                                             // т.к. все элементы массива trans, кроме первого
                                                                             // равны null
                    }
                }
1
31 / 21 / 10
Регистрация: 08.10.2017
Сообщений: 181
15.07.2019, 20:56  [ТС] 17
asn31337, ну как же, это не так. В 20 строчке присваивание есть.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
        public void Det_Count()
        {
           ...
            if ((j > 0))
            {
                if (j == n) // если построена трансверсаль
                {
                    ...
                }
             }
                else // если трансверсали нет
                {
                    for (i = 0; i < Math.Pow(n, p - 1); i++)// в цикле смотрим трансверсальные элементы
                    {
                        int c;
                        c = i;
                        s = indexes[c, j];
                        if (Candidate(s))
                        {
                            trans[j] = indexes[c, j]; //вот тут как раз и идёт присваивание
                            _i[j] = c;
                            _j[j] = j;
                            depth++;
                            Det_Count();
                        }
                    }
                 ...
                }
            }
        }
Самое странно, что это не единственное место, где лезут исключения. В том месте, где присваивание, он лезет в массив indexes по допустимым координатам, но говорит, что вылезает за пределы массива. Также переменные иногда принимают странные значения, которым браться неоткуда.
Все исключения вылезают, если хотя бы два потока работают одновременно. Если всем им давать отрабатывать последовательно, то исключений нет. Потому в самом начале я и спросил, не напутал ли где с вызовом/созданием/еще чем. В целом, вопрос открыт и проблема не ясна.
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
16.07.2019, 13:31 18
Цитата Сообщение от Slepoyi Посмотреть сообщение
В 20 строчке присваивание есть
Все может быть... Но, по крайней мере, когда я смотрел в отладчике в ту часть кода программа не заходила. Т.е. массив так и оставался с одним инициализированным элементом. Проверяйте логику программы.
1
16.07.2019, 13:31
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.07.2019, 13:31
Помогаю со студенческими работами здесь

При запуске программы ошибка Необработанное исключение типа "System.NullReferenceException"
При запуске программы выбивает ошибку Необработанное исключение типа...

При попытке заполнить поле класса выбрасывается исключение "System.NullReferenceException"
При попытке заполнить поле класса выбрасывает исключение &quot;System.NullReferenceException&quot;...

Выходит исключение System.NullReferenceException: "Ссылка на объект не указывает на экземпляр объекта."
Как исправить и что не так? Уже все перепробовал и программа не запускается. Вот код using...

Необработанное исключение типа "System.NullReferenceException"
Здравствуйте! Учу C#. Сейчас на этапе классов. Пробовал создавать объекты и заполнять их разными...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru