Почему я получаю ошибку сегментации, когда я устанавливаю указатель на объект, равный NULL?

Хорошо, поэтому у меня есть программа, которая в основном работает на рынке. У меня очень много работы, и у меня только одна проблема. В какой-то момент в моей программе у меня есть структура таких шашек:

14 struct Checker
 15 {
 16 int m_money_in_register;
 17 int m_start_work;
 18 int m_time_checkout;
 19 Cust *m_cust;
 20 };

Я создаю указатель на массив объектов проверки следующим образом:

118 Checker *checkers = new Checker[num_checkers]; // Initializing all checkers
119 for(int i = 0; i < num_checkers; i++)
120 {
121 checkers[i].m_money_in_register = 500;
122 checkers[i].m_start_work = 0;
123 checkers[i].m_cust = NULL;
124 checkers[i].m_time_checkout = 0;
125 }

Это работает очень хорошо, и когда шашки [i].m_cust = NULL, это означает, что checker доступен, и я могу назначить объект Cust, который находится в моем checkout_queue, для проверки.

Моя программа делает то, что я хочу сделать для первого Cust, который проверяет, однако, когда этот Cust завершен, я хочу установить шашки [i].m_cust = NULL, чтобы он был доступен клиенту еще раз, однако это дает мне ошибку сегментации, и это выглядит следующим образом:

195 if(checkers[i].m_time_checkout == clock && checkers[i].m_cust->get_status() == "shopper" && checkers[i].m_cust != NULL)
196 {
197 int amount_paid = checkers[i].m_cust->get_num_items()*5;
198 checkers[i].m_money_in_register += amount_paid;
199 checkers[i].m_cust->print_done_checkout(cout, clock, amount_paid, i);
200 Cust *tmp = checkers[i].m_cust;
201 delete tmp;
202 num_custs--;
203 checkers[i].m_cust = NULL; // SEG FAULT CAUSED BY THIS
204 }
205
206 if(checkers[i].m_time_checkout == clock && checkers[i].m_cust->get_status() == "robber" && checkers[i].m_cust != NULL)
207 {
208 int checker_cash = checkers[i].m_money_in_register;
209 checkers[i].m_cust->print_done_stole(cout, clock, checker_cash, i);
210 checkers[i].m_money_in_register = 0;
211 Cust *tmp = checkers[i].m_cust;
212 delete tmp;
213 num_custs--;
214 checkers[i].m_cust = NULL; // SEG FAULT CAUSED BY THIS
215 }

Как правильно установить объект в NULL? пример вывода im im выглядит следующим образом:

1: Joe entered store
Should be done at: 7
2: James entered store
Should be done at: 8
3: Bob entered store
Should be done at: 9
4: Abby entered store
Should be done at: 10
5: Leo entered store
Should be done at: 11
7: Joe done shopping
7: Joe started checkout with checker 0
time checkout: 13
8: James done shopping
8: James started checkout with checker 1
time checkout: 14
9: Bob done shopping
10: Abby done shopping
11: Leo done shopping
13: Joe paid $10 for 2 items to checker 0
Segmentation fault

Как я уже сказал, строка 13 - это то, что я хочу, но установка указателя на объект Cust, равный нулю, дает мне ошибку seg. Если требуется какое-либо уточнение или вы хотите передать сообщение GDB, я могу его предоставить. Любой вход оценивается, спасибо!

Весь цикл выглядит следующим образом:

175 for(int i = 0; checker_queue.empty() != true && i < num_checkers; i++)
176 {
177 int checker_number = i;
178 if(checkers[i].m_cust == NULL && checkers[i].m_start_work == 0)
179 {
180 checkers[i].m_cust = checker_queue.dequeue();
181 checkers[i].m_cust->print_start_checkout(cout, clock, checker_number);
182
183 if(checkers[i].m_cust->get_status() == "shopper")
184 {
185 checkers[i].m_time_checkout = clock + (checkers[i].m_cust->get_num_items()*3);
186 }
187
188 else if(checkers[i].m_cust->get_status() == "robber")
189 {
190 checkers[i].m_time_checkout = clock + 7;
191 }
192 cout << "time checkout: " << checkers[i].m_time_checkout << endl; //check for checkout time
193 }
194
195 if(checkers[i].m_time_checkout == clock && checkers[i].m_cust->get_status() == "shopper" && checkers[i].m_cust != NULL)
196 {
197 int amount_paid = checkers[i].m_cust->get_num_items()*5;
198 checkers[i].m_money_in_register += amount_paid;
199 checkers[i].m_cust->print_done_checkout(cout, clock, amount_paid, i);
200 Cust *tmp = checkers[i].m_cust;
201 delete tmp;
202 num_custs--;
203 checkers[i].m_cust = NULL;
204 }
205
206 if(checkers[i].m_time_checkout == clock && checkers[i].m_cust->get_status() == "robber" && checkers[i].m_cust != NULL)
207 {
208 int checker_cash = checkers[i].m_money_in_register;
209 checkers[i].m_cust->print_done_stole(cout, clock, checker_cash, i);
210 checkers[i].m_money_in_register = 0;
211 Cust *tmp = checkers[i].m_cust;
212 delete tmp;
213 num_custs--;
214 checkers[i].m_cust = NULL;
215 }
216 }

Если я прокомментирую установку шашек [i].m_cust = NULL, я получаю больше информации, как показано ниже:

1: Joe entered store
Should be done at: 7
2: James entered store
Should be done at: 8
3: Bob entered store
Should be done at: 9
4: Abby entered store
Should be done at: 10
5: Leo entered store
Should be done at: 11
7: Joe done shopping
7: Joe started checkout with checker 0
time checkout: 13
8: James done shopping
8: James started checkout with checker 1
time checkout: 14
9: Bob done shopping
10: Abby done shopping
11: Leo done shopping
13: Joe paid $10 for 2 items to checker 0
14: James paid $10 for 2 items to checker 1
Segmentation fault
1 ответ

Я подозреваю, что проблема заключается в том, что вы тестируете оптимизированный код, и поэтому представление о том, где происходит сбой, является неправильным. Вероятно, этот код может возникнуть в ваших операторах if:

checkers[i].m_cust->get_status() == "robber" && checkers[i].m_cust != NULL

У вас это неправильно; вам нужно проверить, что m_cust не имеет значения null, прежде чем пытаться вызвать get_status() на нем

checkers[i].m_cust != NULL && checkers[i].m_cust->get_status() == "robber"

т.е.

if(checkers[i].m_time_checkout == clock && checkers[i].m_cust != NULL && checkers[i].m_cust->get_status() == "robber")

При задании двух логических условий И:

если (a && b)

b нужно проверить только если a истинно. C и C++ прекращают оценивать условия, как только они достигают состояния, которое делает остальные тесты ненужными (так называемая "оценка короткого замыкания").

если (a || (b && c))

Если a истинно, b и c не будут оцениваться. c будет оцениваться только в том случае, если a является ложным и b истинно.

-- В стороне --

Cust *tmp = checkers[i].m_cust;
delete tmp;

Я предполагаю, что это часть вашего расследования "что происходит здесь", но вы должны быть в порядке

delete checkers[i].m_cust;

Пока объекты checkers [i].m_cust были выделены индивидуально с помощью "new". Убедитесь, что вы не делаете

Customers* customer = new Customer[someNumber];
...
checkers[i].m_cust = customer[x];
...
delete checkers[i].m_cust; // << BAD

Если ваши клиенты распределяются таким образом, не удаляйте их отдельно, используйте

delete [] customers;

когда вы закончите с ними.

licensed under cc by-sa 3.0 with attribution.