PDA

Просмотр полной версии : [Урок] Как бороться с выходами за пределы массива (CrashDetect)



Daniel_Cortez
06.12.2015, 11:46
Чтобы не объяснять индивидуально каждому в разделе "Вопросы", распишу здесь один распространённый случай, в котором срабатывает CrashDetect.

Допустим, у нас есть скрипт test.pwn:


#include <a_samp>

main()
{
new a[10];
for (new i = 0; i < 20; i++)
a[i] = i;
for (new i = 0; i < 20; i++)
printf("%d", a[i]);
}


При выполнении этого кода плагин CrashDetect выведет сообщение:


[debug] Run time error 5: "Invalid memory access"
[debug] AMX backtrace:
[debug] #0 00000078 in ?? (0x00000000, 0x00000000, 0xf050b5c3) from test.amx
[debug] #1 0000000b in main () from test.amx
Script[gamemodes/test.amx]: Run time error 5: "Invalid memory access"



Для начала откомпилируем код в режиме отладки (в теме про CrashDetect (http://pro-pawn.ru/showthread.php?2991-CrashDetect) написано, как это сделать) и запустим скрипт заново:


[debug] Run time error 4: "Array index out of bounds"
[debug] Accessing element at index 10 past array upper bound 9
[debug] AMX backtrace:
[debug] #0 000000a4 in main () at C:\server\gamemodes\test.pwn:7
Script[gamemodes/test.amx]: Run time error 4: "Array index out of bounds"

Теперь данных в сообщении достаточно, чтобы найти причину ошибки.
"Array index out of bounds" переводится как "выход за пределы массива".
Означает это, что вы что-то пытаетесь сделать с несуществующим элементом массива.

Обратите внимание: в сообщении красным цветом выделен несуществующий элемент, зелёным - максимальный номер элемента в массиве.

[debug] Accessing element at index 10 past array upper bound 9

Ошибка произошла из-за того, что сервер попытался получить доступ к 10-му элементу массива, когда в массиве есть только элементы с номерами от 0 до 9.
Также синим цветом выделено название исходного файла (иногда ошибки возникают не только в .pwn мода, но и в инклудах и фильтрскриптах) и номер строки, на которой произошла ошибка.

[debug] #0 000000a4 in main () at C:\server\gamemodes\test.pwn:7
Смотрим строку №7 в test.pwn:


for (new i = 0; i < 20; i++)

Обратите внимание на условие выхода из цикла: выход происходит только когда i становится равно 20.
При этом размер массива - 10 элементов.

Как нам исправить эту проблему? Нужно сделать так, чтобы цикл был не до 20, а до (<размер массива> - 1).


for (new i = 0; i <= 10 - 1; i++)

Проблема решена? Ещё нет.
Выхода за пределы массива не будет, но что, если в будущем понадобится изменить размер массива, скажем, с 10 до 8?
Представьте себе мод из 30 000 строк кода: вам придётся обыскивать весь мод, чтобы найти, в каких циклах происходит перебор массива, и во всех этих циклах заменять 10 на 8.
Это как бомба замедленного действия: сейчас вы решите проблему, но вместо неё в будущем появится другая.
Чтобы такого не было, в цикле следует использовать оператор sizeof, который возвращает размер массива.


for (new i = 0; i <= sizeof(a) - 1; i++)

Можно немного упростить запись, убрав "- 1" и заменив знак "меньше или равно" на "меньше".


for (new i = 0; i < sizeof(a); i++)


В итоге получится такой код:


#include <a_samp>

main()
{
new a[10];
for (new i = 0; i < sizeof(a); i++)
a[i] = i;
for (new i = 0; i < sizeof(a); i++)
printf("%d", a[i]);
}

Компилируем и запускаем:


0
1
2
3
4
5
6
7
8
9

Код работает без ошибок. Проблема решена.


Автор статьи: Daniel_Cortez (http://pro-pawn.ru/member.php?100-Daniel_Cortez)

Специально для Pro-Pawn.ru (http://www.pro-pawn.ru)
Копирование данной статьи на других ресурсах без разрешения автора запрещено!

DoN_SancheS
01.12.2016, 22:31
Тогда от чего может быть это:

http://ihost.pro-pawn.ru/image.php?dt=DDAD (http://ihost.pro-pawn.ru/?pt=DDAD)

Strong
07.12.2016, 04:28
Тогда от чего может быть это:

http://ihost.pro-pawn.ru/image.php?dt=DDAD (http://ihost.pro-pawn.ru/?pt=DDAD)

От кривых рук

DoN_SancheS
11.12.2016, 12:18
То-есть?
Я понимаю что я сделал что то не так но не понимаю почему ты умничаешь вместо того чтобы помогать.

ziggi
11.12.2016, 12:49
То-есть?
Я понимаю что я сделал что то не так но не понимаю почему ты умничаешь вместо того чтобы помогать.

Ты пытаешься сделать что-то, в чём не разбираешься, тебе нужно сначала изучить основы (http://pro-pawn.ru/showthread.php?4082).

hawertin
31.10.2022, 21:37
А у меня почему то архив не открывается.