Меню

Что значит ошибка выполнения ejudge

#c #scanf #fork

Вопрос:

Почему этот код может генерироваться Runtime Error в ejudge? Эта программа подсчитывает количество stdin введенных слов. Слова могут быть разделены любым количеством ' ' и 'n' . Похоже fork() , это может вызвать проблему, но я не уверен, почему я не получаю ту же ошибку на своем компьютере.

ejudge использует gcc — простой C, 64-разрядный, используя -std=c11 или -std=gnu11

Задача:

В стандартном входном потоке задается текстовая строка, состоящая из слов (последовательность символов, не являющихся пробелами), между которыми может быть любое количество пробелов, включая строки.

Вам нужно рассчитать количество слов, если вы знаете, что их не более 255, и вывести это значение в стандартный поток вывода.

Используйте создание новых процессов, чтобы каждый процесс считывал не более одного слова, например, используя scanf(«%s»,…).

Вы можете вывести результат только из процесса, который был запущен первым (т. Е. из исходной программы).

Полученная программа должна вернуться с кодом возврата 0.

Размер каждого слова не превышает 4096 байт.

Мой код:

 #include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

#define DBG(args...) fprintf(stderr, args)
//#define DBG(args...)

int main(int argc, char* argv[])
{
    int status;
    pid_t pid;
    pid_t first_child;

    for (int i = 0; i < 256;   i) {
        pid = fork();

        if (pid == 0) { // child continue reading
            char str[4097];
            if (scanf("%s", str) != EOF)
                continue;
            exit(1);
        } else {
            if (i == 1) {
                first_child = pid;
            }
            if (wait(amp;status) == first_child) {
                break;
            } else {
                exit(WEXITSTATUS(status)   1);
            }
        }
    }

    fprintf(stdout, "%in", WEXITSTATUS(status));
    fflush(stdout);
    fclose(stdout);

    return 0;
}
 

Комментарии:

1. Почему вы закрываетесь вручную stdout ? Это может привести к ошибке в некоторых системах, когда ваша программа завершает работу и пытается закрыть ее снова. Кроме того, можете ли вы предоставить более подробную информацию об ошибке, которую вы получаете?

2. Кроме того, обратите внимание, что stdin может не получиться EOF даже после того, как закончатся фактические входные данные, это опять же зависит от среды.

3. Статус выхода ограничен 255. Это не сработает, если длина файла превышает 255 строк.

4. Это решение не будет работать, потому что stdio использует буферизацию ввода. scanf() может буферизировать больше входных данных, чем возвращаемое слово, и следующий дочерний процесс не начнет чтение с того места, на котором он остановился.

5. Я думаю if (i == 1) , так и должно быть if (i == 0) .

Ответ №1:

Переписал алгоритм, и он сработал! В первой версии было сделано много ненужных вилок. Например, если предполагалось 6, то создавалось 12.

 #include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

// #define DBG(args...) fprintf(stderr, args)
#define DBG(args...)

int main(int argc, char* argv[])
{
    int status;
    pid_t first_pid;
    pid_t pid = fork();

    if (pid != 0) {
        wait(amp;status);
        printf("%in", WEXITSTATUS(status));
        return 0;
    }

    for (int i = 0; i < 256;   i) {
        char str[4097];
        if (scanf("%s", str) == EOF) {
            DBG("PID %in", pid);
            exit(0);
        }
        pid = fork();
        if (pid != 0)
            break;
    }

    DBG("PID %i waitingn", pid);
    wait(amp;status);
    exit(WEXITSTATUS(status)   1);
}
 

Почему этот код может генерировать Runtime Error в ejudge? Эта программа подсчитывает количество слов из ввода stdin. Слова могут быть разделены любым количеством ' ' и 'n'. Кажется, что fork() может вызвать проблему, но я не уверен, почему я не получаю ту же ошибку на своем компьютере.

Ejudge использует gcc — обычный C, 64-битный, используя -std=c11 или -std=gnu11

Задание:

На стандартный входной поток задается текстовая строка, состоящая из слов (последовательности не пробельных символов), между которыми может быть любое количество пробельных символов, включая переводы строки.

Вам нужно подсчитать количество слов, если вы знаете, что их не более 255, и вывести это значение в стандартный поток вывода.

Используйте создание новых процессов, чтобы каждый процесс читал не более одного слова, например. используя scanf(«%s», …).

Вы можете вывести результат только из процесса, который был запущен первым (т.е. из исходной программы).

Результирующая программа должна вернуться с кодом возврата 0.

Размер каждого слова не превышает 4096 байт.

Мой код:

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

#define DBG(args...) fprintf(stderr, args)
//#define DBG(args...)

int main(int argc, char* argv[])
{
    int status;
    pid_t pid;
    pid_t first_child;

    for (int i = 0; i < 256; ++i) {
        pid = fork();

        if (pid == 0) { // child continue reading
            char str[4097];
            if (scanf("%s", str) != EOF)
                continue;
            exit(1);
        } else {
            if (i == 1) {
                first_child = pid;
            }
            if (wait(&status) == first_child) {
                break;
            } else {
                exit(WEXITSTATUS(status) + 1);
            }
        }
    }

    fprintf(stdout, "%in", WEXITSTATUS(status));
    fflush(stdout);
    fclose(stdout);

    return 0;
}

1 ответ

Переписал алгоритм и все заработало! В первой версии было сделано много ненужных разветвлений. Например, если предполагалось 6, получилось 12.

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

// #define DBG(args...) fprintf(stderr, args)
#define DBG(args...)

int main(int argc, char* argv[])
{
    int status;
    pid_t first_pid;
    pid_t pid = fork();

    if (pid != 0) {
        wait(&status);
        printf("%in", WEXITSTATUS(status));
        return 0;
    }

    for (int i = 0; i < 256; ++i) {
        char str[4097];
        if (scanf("%s", str) == EOF) {
            DBG("PID %in", pid);
            exit(0);
        }
        pid = fork();
        if (pid != 0)
            break;
    }

    DBG("PID %i waitingn", pid);
    wait(&status);
    exit(WEXITSTATUS(status) + 1);
}


0

E1ZY
22 Окт 2021 в 23:38

  1. Что такое ejudge?
  2. Зачем мне делать эти задачи?
  3. Как зарегистрироватьcя?
  4. Я нашел ошибку или уязвимость в системе проверки.
  5. Система проверки выглядит некрасиво!
  6. Стартовая страница и/или этот FAQ выглядят некрасиво!
  7. Я похакал этот сервер!
  8. А сколько баллов мне дадут за %action%?
  9. Почему нет языка %language_name%? Я умею программировать только на нем!
  10. Что означает valgrind рядом с gcc при отправке ответа на C или C++?
  11. Почему тесты проходят так медленно?
  12. У меня ошибка компиляции, но на моем компьютере все работает!
  13. У меня ошибка нарушения безопасности!
  14. У меня тест не прошел, где смотреть ошибку?
  15. У меня правильная программа, но тесты не проходят (на моем компьютере работает)!
  16. Что делать с задачей, у которой статус «ожидает подтверждения»?
  17. У меня появилась идея, как улучшить свое решение, можно мне отправить еще одно? Учтется ли оно как лишняя попытка?
  18. Я нашел ошибку в условии/условие не отображается.
  19. Я нашел ошибку в тесте.
  20. У меня идея для теста / Я написал некорректную программу, но она прошла все тесты.
  21. У меня есть идея для задачи!
  22. Кажется, я нашел пасхалку. Мне за это что-нибудь причитается?
  23. Почему мое решение отклонили?
  24. Почему дисквалифицировали мое решение?
  25. Задача %exercise% решается слишком просто на языке %language_name%, а я пишу на %other_language_name% и там тяжелее!
  26. За что снижаются баллы?
  27. Я сделал все задачи, а мне не дали баллов!
  28. Сколько мне дадут баллов, если задачи в модуле сделаны частично?
  29. Систем начисления баллов несправедлива!
  30. У меня проект состоит из нескольких файлов, как мне их отправить?
  31. Я списал, а мое решение не дисквалифицировали и засчитали задачу!
  32. Что означает сообщение «NOTE: The file checksum has been changed» в файле с ответом?
  33. Я не нашел ответа на свой вопрос.

Что такое ejudge?

Это сервер проверки задач, разработанный Александром Черновым из МГУ. Одна из самых распространенных систем для проведения олимпиад. Системе уже больше 10 лет.

Документация (местами неполная или устаревшая): https://ejudge.ru/wiki/index.php/Система_ejudge

Исходный код: https://github.com/blackav/ejudge

При желании вы можете скачать с официального сайта виртуалку и открыть свой сервер проверки, со Scala и программистками.

Зачем мне делать эти задачи?

Чтобы проверить свои навыки программирования и получить баллы. Ну и в некоторых задачах придется думать, что может пойти не так.

Как зарегистрироватьcя?

Я нашел ошибку или уязвимость в системе проверки.

Проинформируйте преподавателя о ней. Возможно, это проблема касается только этого сервера. Если нет — то, пожалуйста, сообщите об этом разработчику системы на github (создайте тикет описанием проблемы с шагами воспроизведения).

Система проверки выглядит некрасиво!

Стартовая страница и/или этот FAQ выглядят некрасиво!

Раньше это были вообще голые hmtl-страницы без стилей, но благодаря Александру Маковскому они выглядят более пристойно. Если у вас есть предложение, как улучшить внешний вид этих страниц — шлите свои варианты с нескучными обоями на почту.

Я похакал этот сервер!

Хорошо, что хоть кто-то это умеет делать. Пожалуйста, почините все обратно и шлите подробную историю своего хака. Вознаграждение будет.

Пожалуйста, ломайте со своего аккаунта. Ужесточать регистрацию и превращать ejudge в продолжение анекдота про столовую и солонки не хочется.

Экплоиты, особенно приводящие к DoS, старайтесь по максимуму проверять на виртуалке — вы же не хотите подгадить своим одногруппникам, обвалив сервер и задержав им сдачу заданий?

А сколько баллов мне дадут за %action%?

Все хорошие и/или полезные действия будут поощряться. Точное количество баллов определяется преподавателем, главное — не забывайте его своевременно информировать о своих нестандартных действиях.

Почему нет языка %language_name%? Я умею погромировать только на нем!

Язык программирования может отсутствовать по одной из трех причин: он не поддерживается системой проверки, не является безопасным (например, C#) или не распространен.

Список для первых двух категорий смотрите в документации/коде ejudge. Насчет последней категории — обсуждаемо, но учтите, что какой-нибудь Pascal включаться точно не будет, а на 1-2 курсе был предмет «Алгоритмические языки и программирование», в рамках которого студенты должны были усвоить языки программирования C и C++.

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

Что означает valgrind рядом с gcc при отправке ответа на C или C++?

Valgrind — это программа для динамического обнаружения утечек и других ошибок при работе с памятью. Все программы на C и C++ запускаются в ее окружении, поэтому работают медленее. Но зато вам говорят, где у вас проблема при работе с памятью.

Почему тесты проходят так медленно?

Во-первых, программы на C и C++ запускаются в окружении valgrind (см. вопрос про него).

Во-вторых, вы на сервере не один (особенно если это конец семестра/модуля).

В-третьих, у всех запускаемых программ ограничиваются ресурсы (чтобы ваша программа по вычислению суммы двух чисел не сжирала всю память на сервере).

У меня ошибка компиляции, но на моем компьютере все работает!

Убедитесь, что вы написали код с учетом общепринятых стандартов (и например там нет какого-нибудь мусора от известного производителя ПО) и не используете нестандартные библиотеки.

Убедитесь, что вы прочли лог компилятора, который выдала вам система проверки и решили все проблемы.

Дайте посмотреть ваш код лучшему программисту в вашей группе. Если это внезапно вы, то пишите преподавателю.

У меня ошибка нарушения безопасности!

Наверно, вы лезете куда не стоит. Читаете больше файлов, чем надо, создаете лишние файлы, пингуете сервер и т.п.

Если вы пишете на питоне, то тогда это может означать, что вы получили исключение. Интерпертатор питона пытается вам выдать stacktrace, и при этом читает системные файлы (что ему запрещает делать модуль безопасности).

У меня тест не прошел, где смотреть ошибку?

Нажимайте на буквы в табличке!

Картинка с табличкой

У меня правильная программа, но тесты не проходят (на моем компьютере работает)!

Вы внимательно прочитали условие? Скачали тест и отладили программу, по шагам выполняя ее? Обратили внимание на поток ошибок (буква E)? Локализовали ошибку в тесте? Уверены, что ошибка не может быть вызвана каким-нибудь неопределенным поведением или особенностями компилятора? Вы попросили помощи у одногруппников?

Если на все вопросы вы можете с чистейшей совестью ответить «да», тогда высылайте всю информацию преподавателю, с подробным описанием того, что в тесте не так, как должно быть и почему.

См. также вопрос про компиляцию.

Что делать с задачей, у которой статус «ожидает подтверждения»?

Этот статус означает, что ваше решение прошло все тесты, но преподаватель пока еще не посмотрел его исходный код и не одобрил его. Можно делать другие задачи и ждать, когда эта будет проверена преподавателем.

У меня появилась идея, как улучшить свое решение, можно мне отправить еще одно? Учтется ли оно как лишняя попытка?

Если вы присылаете еще одно решение, которое прошло все тесты, то предыдущее решение, прошедшее все тесты, не учитывается как попытка. Таким образом, можно бесплатно дополнять свое решение, например, добавлять поясняющие комментарии, рефакторить или наводить красоту. Проверяется только последнее решение.

Я нашел ошибку в условии/условие не отображается.

Пишите преподавателю, где ошибка, и почему вы считаете, что это ошибка.

Я нашел ошибку в тесте.

Опишите преподавателю максимально подробно, в чем именно заключается ошибка в тесте и какой на самом деле должен быть ответ.

У меня идея для теста / Я написал некорректную программу, но она прошла все тесты.

Отлично! Если вы уверены, что ситуация подходит под условие задачи, то высылайте преподавателю:

  1. исходный код, который прошел все тесты (и номер решения);
  2. описание случая, когда код будет работать некорректно;
  3. входные данные для теста, который покрывает этот случай — текстовый файл;
  4. выходные данные для теста — текстовый файл;
  5. исправленный исходный код, который проходит тест.

В качестве альтернативы вы можете предложить изменения в тексте условия задачи, которые исключат этот случай.

У меня есть идея для задачи!

Очень хорошо. Обсудите идею с товарищами. Обсудите с преподавателем и подумайте, куда эту задачу лучше приткнуть.

Возможно, задача потянет на ДЗ.

Кажется, я нашел пасхалку. Мне за это что-нибудь причитается?

Пасхалки — это прикольно. Возможно, они есть даже на этой странице. Первый, кто на потоке нашел пасхалку, получит баллы.

Почему мое решение отклонили?

Причин может быть несколько: вы не выполнили какое-нибудь условие задачи (например, в условии написано «выделять память только один раз», а вы выделяете ее на каждый чих), вы прислали обфусцированный код, вы прислали код, в котором захардкожены все тесты, в вашем коде есть какая-то неимоверная дичь, от которой захотелось выколоть себе глаза и т.д.

Если вы считаете отклонение несправедливым, самый справедливый суд в лице преподавателя готов рассмотреть вашу аппеляцию: шлите ее на почту.

Почему дисквалифицировали мое решение?

Проверяющая система решила, что ваш код очень похож на чужой, и есть сомнения, что решение вы выполнили полностью самостоятельно. Статус «дисквалифицировано» означает, что преподаватель посчитал так же.

Если вы считаете дисквалификацию несправедливой, самый справедливый суд в лице преподавателя готов рассмотреть вашу аппеляцию (присылайте ее на почту в свободной форме). Имейте в виду, что решение может быть пересмотрено и в худшую для вас сторону. Если вы отправите чужой код еще раз, то за модуль ejudge вы не получите баллов вообще (даже если потом полностью и честно сделаете сами).

Дополнительные вопросы по этой теме:

Но ведь невозможно написать 2 программы по одному условию, чтобы они не были похожи!

Многолетний опыт показывает, что возможно. В конце концов сдавали же как-то люди свои работы в прошлом году.

Я просто взял решение друга, чтобы посмотреть, как он сделал, но писал код сам!

Очевидно, вы слишком мало потрудились, чтобы сделать именно свое решение и банально перепечатали чужое. В следующий раз делайте полностью самостоятельно.

Я сдал код первым, я не мог ни у кого списать!

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

Задача %exercise% решается слишком просто на языке %language_name%, а я пишу на %other_language_name% и там тяжелее!

Черт побери, так решите ее на %language_name%, в чем проблема-то? Выбирайте инструмент под задачу.

За что снижаются баллы?

Баллы снижаются за количество попыток (но некоторое число попыток на задачу — бесплатно), за отклонение решения, за выполнение модуля не в срок.

Я сделал все задачи, а мне не дали баллов!

К сожалению, преподавателю иногда надо спать и заниматься другими менее приятными делами, поэтому он реагирует не мгновенно. Задачи проверяются массово в конце модуля и иногда в середине.

Сколько мне дадут баллов, если задачи в модуле сделаны частично?

Баллы начисляются только за полностью выполненный модуль, в котором все задачи проходят все тесты, а исходных код проверен преподавателем.

Систем начисления баллов несправедлива!

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

У меня проект состоит из нескольких файлов, как мне их отправить?

К сожалению, это ограничение системы ejudge. Возможно, кто-то невнимательно прочитал документацию. Если вы найдете способ, как настроить ejudge так, чтобы он корректно обрабатывал проекты из нескольких файлов — пишите.

Большинство языков позволяют создать программу, полностью расположенную в одном файле. Соответственно, вы можете найти/написать скрипт, который пакует ваш проект в один файл (или сделать это вручную).

Я списал, а мое решение не дисквалифицировали и засчитали задачу!

Это можно рассматривать как уязвимость системы проверки. При явке с повинной вам не только оставят баллы, но еще и сверху накинут. Но, разумеется, надо описать, как вы это сделали.

Что означает сообщение «NOTE: The file checksum has been changed» в файле с ответом?

Это служебное сообщение системы ejudge о том, что контрольная сумма файла ответа на тест была изменена во время тестирования.

Но, разумеется, никто его не менял и это баг системы, о котором было доложено разработчику.

На корректность вашей программы это сообщение никак не влияет. Если программа завалилась на этом тесте — надо ее исправить, если нет — не надо.

Я не нашел ответа на свой вопрос.

Задавайте его в чате. Возможно он потом попадет в этот FAQ.

���������� �� ������������� �������������� ����������� ������� EJudge ��� ���������.

  1. ����� � ������� ��� ��������� ������� ��� ������������������:
    1. ��������� (�� ������������, ����������� � �.�.):
      1. �������� � ������������� ����� � ������, ������� � ���� ���� �������, ��� � ����� ������.
      2. �������� �������� �� ������, ���������� ��������������, ������� ��� ����� � ������.
      3. ���������� � ������ 1.4.2.2 ������ ������� (����������� ������ �������� � ������ ��������).
    2. ������ ����������� �� ��������� ������������ � �������� (������ �� ����, ������� �������� � �.�.):
      1. ���� � ��� ��� ���� �������, �� ���������� � ������ 1.4.2 ������ ������� (����������� ������ �������� � ������ ��������).
      2. ���� � ��� ��� �������� ��� �� ������ ������� ������, �� ���ģ��� ������������������ �� ������ ��������� (����� 1.4.1, �������� �ޣ���� ������ (��������)).
    3. ��������� ������ � ���� (� �.�. ������ ������������ ��������/�����������):
      1. ������� �� ������ ����� �� ������� [%username%].
      2. �� �������� ���� ������������ ������� ������ �����������.
      3. ������� � �������, ����� ���� ����� � ������.
      4. �������������� ���������� � ���� — ��. ����� 1.4.2.3, ����������� ������ �������� � ������ ��������.
    4. ��������� ����������� � �������
      1. �������� �ޣ���� ������ (��������):
        1. ��������� �� �������� ����� � �������.
        2. ���� ���� ������ �����������, ��������� �� ���.
        3. ��������� �� ������ ������� ������� ������.
        4. ����������/��������� �ݣ �� ������� ����� �����, ������� ��� � ��������������� ����.
        5. ������� ��� e-mail.
        6. � ������� ���� �������� � ������ � ���������� ���������� �����������. ��� ���������� ��������� �� ����� ������������ ���� ����������� ����� ������, ��������� �� ��������� e-mail, �.�. � ���� ������ ������ ����� �� ����������, ��� ��� ����� ������� ����� �����.
        7. ������� �� ������ ������� �ޣ���� ������.
        8. ������� ����������� ��� ��� ������ � ������� ��� �� ��������� ��������. ���� �������� ���, ���� ����� �� ����� ����� � ������� �������� �� �����, ������� �� �������� (�� ������ ��������� (������ ����� ������)).
        9. ������� �� ������ �����.
      2. ����������� ������ �������� � ������ ��������:
        1. ���� �� ���������� �� �������� ���� ������������, ��������� �� ������ �����������, ������� ���� ����� � ������ � ������� �� ������ �����.
        2. ������� �� ������ �� ��������������� [����������� �����������].
        3. � ����������� �������� ��������� ��������������� ���������� � ���� (���, ����� ������, ������� ��������� � �.�.). ��� ����� ������� �� ������ ����� ���������� [�������������] � ��������� ����������� ����. ������� ������ ���������.
        4. ����� ����������� ����� ��������� � ������� ���Σ���, �� �������� �������� ����� ���������� �������� ������ ����������� (������ ����� ������). ������� �� �ţ � ����������� � ������� �����.
  2. ������� �� ������ (�������) ������ � ��������� ������ (���� �� �������, ��� ��� ���� — �������� ���� � �������� �� ��������).
  3. ����������� ���������� ������� ������. ���������� ������� ����, ��� ����� ��������� ����� ���������� �� ���� � ��� ��������� �� ������.
  4. ��������, ��������� (!), �������������, ��������� (!) � ��������� ��������� � ���� �� ����������. ��������� ������ ���� ��������� � ���� � �����-�� ������ � ������ � ��������� ��� �����. ���� ��������� ������� ��������, ������� �� �������� ����� ����������� �������. ������ �����������: ����������� � ������� ������ �������� ���� (��� C/C++ ��� ����� � ������������ .c � .cpp), � �� ������ ����� ��������, ������� (.vcproj) ��� �������� ����������� ����� (.exe). ��� ����, ����� �������� ��������, �������� � ������������ ������� ����������� ���������� ������ ���/� �������� ����, ������� �� ����������� ����������, � �������� (��� ������ ��������� ���������) � ���������, ��� ��� � ���� ���� �������� ���������. ���� �� ������ �����, ���� �� ���������. ����� � EJudge ������� �� ������ Browse (�����) � �������, ��� �� ���������� ����� �������� ��������� ���� � ����������.
  5. � ���������� ������ ���� �������� ����, �� ������� �� �������� ���������, ��������:
    • ��� C: gcc - GNU C 4.7.2
    • ��� C++: g++ - GNU C++ 4.7.2
    • ��� Pascal: fpc - FreePascal 2.6.0
    • ��� Basic: yabasic - YaBasic 2.763
  6. ������� �� ������ ���������! ��������� �������� �������. ���� ������� ������ ��������� � ������� ������� (���� ������ ���������), �� ������ �������������.
  7. �������� �������� (������� F5 � ��������), ����� ���������� ���������� �������� ������ ��������.
  8. ���� ��������� �������� �� ��, �� ����� � ������� ���������� �������� ������ �� ������ �������� � ����������, ����� ����� �� ������ � ������. ��� �������, �������� ������������� �� ��� �����, � ������ ������ 1-2.
    • ���� �� ������ �� ����� �, ���������, ��� � ����� ������ ������������ ������ n.
    • ���� �� ������ �� ����� �, ����������� ������ �� ������������ ����� � �������, ������� ������ � �������� ����� �� C89/C99 (��������, ����������� stdio.h, stdlib.h, string.h, math.h
      �� ����������� conio.h, io.h, dos.h, stdafx.h).
    • ��� ����� ���������� �� �������� ����������� ���������� ��������� � ����� (�� ����������� ������� getch(), system(«PAUSE») � �.�.). ���� ���� ��������� �������������� �� �������, ��� ��� ������� �������� ����������� �� �������, � ������� �����, ��� ���� ��������� �������. ��� ��������� ���������� ����� ��������� ����� ţ ���������� ���� ������ ������� (� M$ Visual — ����� ���� Debug -> Start Without Debugging).
    • ������ ���������� — ���� ��������� �� �������������. ��� ����� ���� ������� ���������� ���������:
      • � ����� ��������� ������,
      • �� ������� �� ��� ����, ����� �������� �������,
      • �� ����������� ������������� ������� C/C++, ������� ��� � Linux (EJudge �������� ������ �� Σ�), ��������, getch(), itoa() � ��.,
      • �� ������ ���������� ����������� ������������ ���� (��������, ��������� system(«PAUSE»), �� ������ ���������� stdlib.h). ���� �� ����� ������� (������), � C++ — ���.
    • ������������ ����� — ����������� ������� ����� ������� ����� � �����, ������� ��� �������. �� ����� (�����) ��������� �������. ���� ����� ���������, �� � ��� ������ � �������. ���� � ������ ����� ������� �����, �� ����������, ���������� �� �� ����� ����������� (�������� �������� �� ��, ����� ����� — ������� ��� ���������).
    • ������������ ������ ������ — ����� ���� ��������� ������ ����������, ��������, ���� �����, � ��� �������� ��� �����, ��� ���� ����� � �����-�� �����, ��� ���������� ����� ������, ��� ���� ���������� ��� �����, � ��� �������� �� ������ (����������� ������� �� ������� ����������, ����� ������, ��� �� ������ ��������� ���� ����� � ������ ������). ���� � ������� ������ ������� ������� ��� ����� ����� ������, ��������� ����� ������� ������, � �� �������, ��������� ��� ������ �����. ������� ��������� ������� ������ ������� � ����� ������ � �� ������ �� ���.
    • ��������� ������������ ����� ������ — �� ����� ��������� ����������� ������, ��� ���������. ���������� �������� ������� / ������������. �����, ��������� ������ �����������?
    • ������ ���������� (Runtime Error) — ���� ��������� ������� �� ������� ��� ��������. ��� ����� ������� ����� �� ���� ������:
      • ���� ��������� ��������� ������������ �������� �� ����� ����������, ��������, �������� �� 0.
      • ���� ��������� �������� �� C/C++ � �� ������������ ���������� ������� main � ����� ��������, �� ������ 0 (������ �������� return 0; ?).
    • ������ ������� (System error) — ��� ������ �� ������ ���������. ��� ��������, ��� �� ����� �������� ������ ������� � ������� �������� �����-�� ������ (������� �� ����� ����� ����������� ������, ��� ��� ���������� ����������� ��������� �������� ������ ����������). ����� ����, � ������ ElJudge, ��� ����� �������� Memory Limit Exceeded. ���� �������� ����� ������ — ������ ������ � ������������� ��� ��������������.
  9. �� ������ �������������� ������� �� ������ � ��� ����� ��������� ��������� ���������� ������. �� ��������������� � �� ���������� ����� �������� ��������: ��� ������� ������ ����-�����, � ����� ���, ��� ����� ���������� ������� � �������, ����������� ��������� �� � ����.
  10. ���� ��������� �������� ��, �� ��������� � ������� ��������� ������, ����� �� ������ ��������� ������ (���� ������� �������).
  11. ������������� ����� �������� ����� �� ��������� ������ �� ������. ���� �������� ���������� ������ ������:
    • ����� — �� ���� �� ����� ������� ������,
    • ������� — ������ ������ �������,
    • ������� — �������� �������,
    • ����� — ������� ������.
  12. ����� ���������� ��� ��������� � ����� ������� ����������, ����� �� ������ ��������� ����������.
  13. ����� ������ ������ �� ������� ������ ��������� �������������, ����� �� ������ ��������� ������, � �� ������ ��������� ��������� �����. �����, ���� ������ ��̣��� ������� ������ ���� �� ������� ������ ������� 1 ������������� ��������� / ������ ����, �� ����� ����������� ���������, ��������, ��� ������ ��� ���-�� �������.

— TatyanaDerbysheva — 31 Aug 2011

  • ��� �������� ������� �����:
    ejudge_task1.png
-*- mode: text; mode: auto-fill; coding: koi8-r -*- $Id$ Часто задаваемые вопросы ======================== Q.1. С помощью программы ejudge-setup был создан настроечный скрипт, однако при запуске он завершается с ошибкой bash: uudecode: command not found Installation of ejudge.xml failed A. Необходимо проинсталлировать программу uudecode. Обычно она находится в пакете sharutils. Для руководства по инсталляции пакетов обратитесь к документации по Вашему дистрибутиву Linux. Q.2. При запуске тестового турнира из-под пользователя root программа userlist-server успешно запустилась, однако при старте программы serve выдаётся ошибка DATE:error:teamdb_open_client: cannot became an admin process: permission denied где DATE — текущие дата и время A. Если посмотреть на сообщения программы userlist-server, можно увидеть строку типа DATE:error:ADMIN_PROCESS: PID, 0 -> root is not allowed здесь PID — идентификатор процесса serve Это означает, что программу serve просто нельзя запускать из-под пользователя root. На самом деле никакую программу системы ejudge категорически не рекомендуется запускать из-под пользователя root. Дело в том, что возможность запуска произвольных программ, вообще говоря, неизвестными пользователями, создаёт сама по себе проблему в безопасности системы, а запуск программ из-под пользователя root делает эту проблему вообще нерешаемой. Необходимо либо запускать программы из-под какого-нибудь непривилегированного пользователя, либо (что даже лучше) создать специального пользователя только для использования системой ejudge. Полезные советы =============== 1. Как компилировать решения на другом компьютере Компиляция программы, как правило, не занимает много времени, поэтому обычно оказывается достаточным запускать сервер компиляции compile на том же компьютере, на котором работает сервер турнира serve. Тем не менее, может возникнуть ситуация, когда и компиляцию программ предпочтительнее выполнять на отдельном компьютере. Этот компьютер может и тестировать решения, а может быть специально выделен только для компиляции. Сначала рассмотрим случай, когда на все турниры запускается единственный сервер компиляции, к которому обращаются серверы турниров. В частности, такая конфигурация генерируется программой ejudge-setup и рекомендуется к использованию. Обозначим через MAIN-COMP-HOME каталог, в котором на серверном компьютере запускается сервер компиляции. Например, это может быть каталог /home/judges/compile — значение, предлагаемое программой ejudge-setup по умолчанию, если не было задано никаких опций скрипта configure. Программа compile получает запросы на компиляцию программ и выдаёт результат компиляции с помощью специальным образом организованных каталогов в файловой системе, поэтому для работы программ `serve’ и `compile’ на разных машинах необходимо, чтобы они могли использовать некоторую общую файловую систему. Например, этого можно добиться проэкспортировав каталог /home/judges на серверном компьютере с помощью NFS (см. описание файла /etc/exports в документации по операционной системе) и примонтировав его на другом компьютере. Кроме NFS можно использовать любую другую файловую систему, например, SMB. Пусть MOUNT-COMP-HOME — это каталог, в котором находится серверный каталог MAIN-COMP-HOME на компьютере, на котором предполается запускать сервер компиляции. Пусть COMP-HOST — это имя этого компьютера. Например, если на компьютере COMP-HOST каталог /home/judges монтируется как /mnt/server/judges, то значением MOUNT-COMP-HOME будет /mnt/server/judges/compile, если значение MAIN-COMP-HOME равно /home/judges/compile. Очень важно, чтобы в качестве рабочего каталога программа `compile’ использовала каталог не на сетевой файловой системе. Настройки программы `compile’ по умолчанию таковы, что в качестве рабочего каталога будет использоваться каталог MAIN-COMP-HOME/var/work/compile, и эту настройку необходимо поменять. В противном случае возможна ситуация, что несколько программ `compile’, работающих на разных компьютерах, будут одновременно использовать один и тот же рабочий каталог, что может привести к непредсказуемым результатам. Чтобы изменить рабочий каталог программы `compile’ достаточно в её конфигурационном файле (MAIN-COMP-HOME/conf/compile.cfg) добавить определение переменной `work_dir’, например, следующим образом: work_dir = /tmp/ejudge Определение этой переменной должно находиться в секции определения глобальных переменных, то есть до секций описания языков программирования. Каталог /tmp выбран потому, что он обычно является локальным (не сетевым) для каждого компьютера в сети. Теперь необходимо исправить конфигурационный файл compile.cfg так, чтобы в нём были прописаны корректные пути с точки зрения компьютера COMP-HOST, так как изначально в нём прописаны пути для серверного компьютера, которые могут быть неверны для компьютера COMP-HOST. Проще всего это сделать заменив определение конфигурационной переменной root_dir на определение в зависимости от имени текущего компьютера: @if host == «COMP-HOST» root_dir = MOUNT-COMP-HOME @else root_dir = MAIN-COMP-HOME @endif Таким образом, файл compile.cfg должен быть отредактирован следующим образом: ==== старая версия ==== root_dir = MAIN-COMP-HOME ==== новая версия ==== @if host == «COMP-HOST» root_dir = MOUNT-COMP-HOME @else root_dir = MAIN-COMP-HOME @endif work_dir = /tmp/ejudge ==== Теперь всё готово к тому, чтобы запускать программу `compile’ на компьютере COMP-HOST. Выполните команды: cd MOUNT-COMP-HOME EJUDGE-BIN-DIR/compile conf/compile.cfg Обратите внимание, что в такой конфигурации возможна параллельная работа двух compile: на главном серверном компьютере и на компьютере COMP-HOST. Добавление новых компьютеров для компиляции выполняется аналогично. 2. Как тестировать решения на другом компьютере 3. Как тестировать решения на нескольких компьютерах 4. Как тестировать несколько турниров на одном компьютере одновременно 5. Как тестировать несколько турниров одной программой run

05.10.2014

Установка ejudge в Ubuntu 20.04 LTS / Alexey Nurgaliev


ejudge — система для проведения онлайн-соревнований по программированию.
Документация системы

Будет рассмотрена установка версии 3.8.0.

Предварительная настройка

Загрузка и установка пакетов. Создается пользователь и группа ejudge.
Также создаются рабочие каталоги.

#!/bin/bash

#Зависимости и компиляторы
sudo apt-get update
sudo apt-get install -y sendmail ncurses-base libncurses-dev libncursesw5 
  libncursesw5-dev expat libexpat1 libexpat1-dev zlib1g-dev libelf-dev 
  g++ gawk apache2 gettext fpc mc openjdk-8-jdk 
  libcurl4-openssl-dev libzip-dev uuid-dev bison flex 
  mono-devel mono-runtime mono-vbnc php7.4-cli perl 
  ruby python python3 gccgo locales net-tools

sudo locale-gen en_US.UTF-8 ru_RU.UTF-8

#Установка FreeBASIC x86_64 (нет в репозитории)
wget -O freebasic.tar.gz http://downloads.sourceforge.net/fbc/FreeBASIC-1.03.0-linux-x86_64.tar.gz?download
sudo tar -xvf freebasic.tar.gz -C /opt/
cd /opt/FreeBASIC-1.03.0-linux-x86_64/
sudo ./install.sh -i
cd

#Или FreeBASIC x86 для 32-битных ОС
#wget -O freebasic.tar.gz http://downloads.sourceforge.net/fbc/FreeBASIC-1.03.0-linux-x86.tar.gz?download
#sudo tar -xvf freebasic.tar.gz -C /opt/
#cd /opt/FreeBASIC-1.03.0-linux-x86/
#sudo ./install.sh -i
#cd

#Создание группы и пользователя ejudge
sudo groupadd ejudge
sudo useradd ejudge -s /bin/bash -m -d /home/ejudge -g ejudge
sudo adduser ejudge sudo

#Создание рабочего каталога judges
sudo mkdir -p /home/judges /home/judges/test_work
sudo chown ejudge:ejudge /home/judges /home/judges/test_work
sudo chmod 0755 /home/judges /home/judges/test_work

#Каталоги сервера
sudo mkdir -p /var/www/ejudge/cgi-bin
sudo mkdir -p /var/www/ejudge/htdocs
sudo chmod 0777 /var/www/ejudge/cgi-bin /var/www/ejudge/htdocs

#Включение модуля CGI
sudo a2enmod cgi
sudo service apache2 restart

Собирать и устанавливать лучше под пользователем ejudge.
Пример, как можно сменить пользователя: sudo su ejudge

#!/bin/bash

cd /home/ejudge

#Загрузка ejudge
wget --no-check-certificate http://www.ejudge.ru/download/ejudge-3.8.0.tgz
tar -xvzf ejudge-3.8.0.tgz

cd ejudge

#Сборка
./configure --prefix=/home/ejudge/inst-ejudge 
            --enable-contests-home-dir=/home/judges 
            --with-httpd-cgi-bin-dir=/var/www/ejudge/cgi-bin 
            --with-httpd-htdocs-dir=/var/www/ejudge/htdocs 
            --with-primary-user="ejudge" 
            --with-exec-user="ejudge" 
            --with-compile-user="ejudge" 
            --enable-ajax 
            --enable-charset=utf-8

make
make install

Конфигурация

Запуск программы конфигурации: /home/ejudge/ejudge/ejudge-setup

Нужно указать Test Working Dir/home/judges/test_work

Также нужно не забыть указать данные администратора в разделе Administrator identity

Сохранить конфигурацию в файл ejudge-install.sh.

Установка

Запустить от имени root: sudo /home/ejudge/ejudge/ejudge-install.sh

Запуск

Запускается система только от имени пользователя ejudge!

Переход в каталог установки: cd /home/ejudge/inst-ejudge/bin

Формирование ресурсов для веб-интерфейса: ./ejudge-upgrade-web

Запуск ejudge: ./ejudge-control start

Настройка apache2

Пример конфигурации виртуального хоста для apache2 версии 2.4
(файл /etc/apache2/sites-enabled/ejudge.conf, возможно потребуется удалить существующую конфигурацию):

<VirtualHost *:80>
    DocumentRoot /var/www/ejudge/htdocs

    ScriptAlias /cgi-bin/ "/var/www/ejudge/cgi-bin/"

    <Directory "/var/www/ejudge/cgi-bin">
        Options +ExecCGI +FollowSymLinks +Includes
        AllowOverride None
        Require all granted
    </Directory>

    <Directory "/var/www/ejudge/htdocs">
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

Перезапустить apache: service apache2 restart

ejudge будет доступен по адресу http://localhost/cgi-bin/serve-control

Настройка nginx

Пример настройки nginx + fcgiwrap.

Установка пакетов:

#Удаление apache
sudo apt-get remove --autoremove apache2

#Установка nginx
sudo apt-get install nginx fcgiwrap

Конфигурация сервера (файл /etc/nginx/sites-enabled/ejudge):

    server {

     listen 80;
     server_name localhost;
     root /var/www/ejudge/htdocs/;

     location ~ ^/cgi-bin/.* {
            gzip           off;
            root           /var/www/ejudge/;
            fastcgi_pass   unix:/var/run/fcgiwrap.socket;

            fastcgi_param  QUERY_STRING       $query_string;
            fastcgi_param  REQUEST_METHOD     $request_method;
            fastcgi_param  CONTENT_TYPE       $content_type;
            fastcgi_param  CONTENT_LENGTH     $content_length;

            fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
            fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
            fastcgi_param  REQUEST_URI        $request_uri;
            fastcgi_param  DOCUMENT_URI       $document_uri;
            fastcgi_param  DOCUMENT_ROOT      $document_root;
            fastcgi_param  SERVER_PROTOCOL    $server_protocol;

            fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
            fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

            fastcgi_param  REMOTE_ADDR        $remote_addr;
            fastcgi_param  REMOTE_PORT        $remote_port;
            fastcgi_param  SERVER_ADDR        $server_addr;
            fastcgi_param  SERVER_PORT        $server_port;
            fastcgi_param  SERVER_NAME        $host;
        }
    }

Конфигурация основана на статье в debian wiki.

ejudge также будет доступен по адресу http://localhost:80

Проверка установки

Если все сделано правильно, то административный интерфейс ejudge будет доступен по адресу
http://localhost/cgi-bin/serve-control

Ситуация: заказчик попросил разместить на странице кликабельную картинку, а чтобы на неё обратило внимание больше посетителей, попросил сделать вокруг неё моргающую рамку. Логика моргания в скрипте очень простая:

  1. В первой функции находим на странице нужный элемент.
  2. Добавляем рамку с какой-то задержкой (чтобы она какое-то время была на экране).
  3. Вызываем функцию убирания рамки.
  4. Внутри второй функции находим тот же элемент на странице.
  5. Убираем рамку с задержкой.
  6. Вызываем первую функцию добавления рамки.

Код простой, поэтому делаем всё в одном файле:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Pulse</title>
	<style type="text/css">
	/*	рамка, которая будет моргать	*/
		.pulse { box-shadow: 0px 0px 4px 4px #AEA79F; }
	</style>
</head>
<body>
	<div id="pulseDiv"> 
    	<a href="#">
      		<div id="advisersDiv">
        		<img src="https://thecode.media/wp-content/uploads/2020/08/photo_2020-08-05-12.04.57.jpeg">
        	</div>
      	</a>
</div>
<!-- подключаем jQuery -->
<script src="https://yastatic.net/jquery/3.3.1/jquery.min.js" type="text/javascript"></script>
<!-- наш скрипт -->
<script type="text/javascript">
	// добавляем рамку
	function fadeIn() {
		// находим нужный элемент и добавляем рамку с задержкой
  	$('#pulseDiv').find('div#advisersDiv').delay(400).addClass("pulse");
  	// затем убираем рамку
  	fadeOut();
	};
	// убираем рамку
	function fadeOut() {
		// находим нужный элемент и убираем рамку с задержкой
   	$('#pulseDiv').find('div#advisersDiv').delay(400).removeClass("pulse");
   	// затем добавляем 
   	fadeIn();
	};
	// запускаем моргание рамки
	fadeIn();
</script>

</body>
</html>

Но при открытии страницы в браузере мы видим, что ничего не моргает, а в консоли появилась ошибка:

❌ Uncaught RangeError: Maximum call stack size exceeded

Что это значит: в браузере произошло переполнение стека вызовов и из-за этого он не может больше выполнять этот скрипт.

Переполнения стека простыми словами означает вот что:

  1. Когда компьютер что-то делает, он это делает последовательно — 1, 2, 3, 4.
  2. Иногда ему нужно отвлечься от одного и сходить сделать что-то другое — а, б, в, г, д. Получается что-то вроде 1, 2, 3 → а, б, в, г, д → 4.
  3. Вот эти переходы 3 → а и д → 4 — это компьютеру нужно запомнить, что он выполнял пункт 3, и потом к нему вернуться.
  4. Каждое запоминание, что компьютер бросил и куда ему нужно вернуться, — это называется «вызов».
  5. Вызовы хранятся в стеке вызовов. Это стопка таких ссылок типа «когда закончишь вот это, вернись туда».
  6. Стек не резиновый и может переполняться.

Что делать с ошибкой Uncaught RangeError: Maximum call stack size exceeded

Эта ошибка — классическая ошибка переполнения стека во время выполнения рекурсивных функций.

Рекурсия — это когда мы вызываем функцию внутри самой себя, но чуть с другими параметрами. Когда параметр дойдёт до конечного значения, цепочка разматывается обратно и функция собирает вместе все значения. Это удобно, когда у нас есть чёткий алгоритм подсчёта с понятными правилами вычислений.

В нашем случае рекурсия возникает, когда в конце обеих функций мы вызываем другую: 

  1. Функции начинают бесконтрольно вызывать себя бесконечное число раз.
  2. Стек вызовов начинает запоминать вызов каждой функции, чтобы, когда она закончится, вернуться к тому, что было раньше.
  3. Стек — это определённая область памяти, у которой есть свой объём.
  4. Вызовы не заканчиваются, и стек переполняется — в него больше нельзя записать вызов новой функции, чтобы потом вернуться обратно.
  5. Браузер видит всё это безобразие и останавливает скрипт.

То же самое будет, если мы попробуем запустить простую рекурсию слишком много раз:

Что означает ошибка Uncaught RangeError: Maximum call stack size exceeded

Как исправить ошибку Uncaught RangeError: Maximum call stack size exceeded

Самый простой способ исправить эту ошибку — контролировать количество рекурсивных вызовов, например проверять это значение на входе. Если это невозможно, то стоит подумать, как можно переделать алгоритм, чтобы обойтись без рекурсии.

В нашем случае проблема возникает из-за того, что мы вызывали вторые функции бесконтрольно, поэтому они множились без ограничений. Решение — ограничить вызов функции одной секундой — так они будут убираться из стека и переполнения не произойдёт:

<script type="text/javascript">
// добавляем рамку
function fadeIn() {
	// находим нужный элемент и добавляем рамку с задержкой
	$('#pulseDiv').find('div#advisersDiv').delay(400).addClass("pulse");
	// через секунду убираем рамку
	setTimeout(fadeOut,1000)
};
// убираем рамку
function fadeOut() {
	// находим нужный элемент и убираем рамку с задержкой
 	$('#pulseDiv').find('div#advisersDiv').delay(400).removeClass("pulse");
 	// через секунду добавляем рамку
	setTimeout(fadeIn,1000)
};
// запускаем моргание рамки
fadeIn();
</script>

Что означает ошибка Uncaught RangeError: Maximum call stack size exceeded

Вёрстка:

Кирилл Климентьев

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ятрогенная патология врачебные ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Что значит ошибка err empty response