Ошибка рекурсии: не удалось проверить, является ли данное число сильным числом или нет [дублировать]

Предположим, у вас есть большой проект, написанный на c ++, который содержит тысячу файлов .cpp и тысячу файлов .h. И давайте предположим, что проект также зависит от десяти статических библиотек. Скажем, мы работаем над Windows, и мы строим наш проект в Visual Studio 20xx. Когда вы нажимаете Ctrl + F7 Visual Studio, чтобы начать компиляцию всего решения (предположим, что у нас есть только один проект в решении)

В чем смысл компиляции?

  • Visual Studio выполните поиск в файле .vcxproj и начните компилировать каждый файл с расширением .cpp. Порядок компиляции не определен. Поэтому вы не должны предполагать, что файл main.cpp скомпилирован сначала
  • . Если файлы .cpp зависят от дополнительных файлов .h, чтобы найти символы, которые могут или не могут быть определены в файл .cpp
  • Если существует один .cpp-файл, в котором компилятор не смог найти один символ, ошибка времени компилятора вызывает сообщение Символ x не может быть найден
  • Для каждого файла с расширением .cpp создается объектный файл .o, а также Visual Studio записывает вывод в файл с именем ProjectName.Cpp.Clean.txt , который содержит все объектные файлы, которые должны обрабатывается компоновщиком.

Второй этап компиляции выполняется Linker.Linker должен объединить весь объектный файл и построить окончательно вывод (который может быть исполняемым или библиотекой)

Шаги при связывании проекта

  • Разберите все объектные файлы и найдите определение, которое было объявлено только в заголовках (например: Код одного метода класса, как указано в p повторные ответы или событие инициализация статической переменной, которая является членом внутри класса)
  • Если один символ не может быть найден в объектных файлах, он также выполняется в дополнительных библиотеках. Для добавления новой библиотеки в project Свойства конфигурации -> Каталоги VC ++ -> Библиотечные каталоги, и здесь вы указали дополнительную папку для поиска библиотек и Свойства конфигурации -> Linker -> Input для указания имени библиотеки. -Если линкер не смог найти символ, который вы пишете в одном .cpp, он вызывает ошибку времени компоновщика, которая может звучать как error LNK2001: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ)

Наблюдение

  1. После того, как Linker найдет один символ, он не ищет в других библиотеках для него
  2. Порядок ссылок на библиотеки имеет значение.
  3. Если Linker находит внешний символ в одной статической библиотеке, он включает в себя символ на выходе проекта. Однако, если библиотека является общей (динамической), он не включает в себя код (символы) на выходе, но Run-Time могут возникнуть сбои

Как решить эту ошибку

Ошибка времени компилятора:

  • Убедитесь, что вы правильно выполнили синтаксический проект c ++.

Ошибка времени компоновщика

  • Определите все символы, которые вы объявляете в ваших файлах заголовков.
  • Используйте #pragma once, чтобы компилятор не включал один заголовок если он уже был включен в текущий .cpp, который скомпилирован
  • Убедитесь, что ваш exter nal library не содержит символов, которые могут вступать в конфликт с другими символами, которые вы определили в ваших файлах заголовков.
  • Когда вы используете шаблон, чтобы убедиться, что вы включаете определение каждой функции шаблона в файл заголовка для разрешения компилятор для создания соответствующего кода для любых экземпляров.
2
задан BartoszKP 17 November 2013 в 20:00
поделиться

5 ответов

Попробуйте заменить:

def fact(n):
    return 1 if(n == 1) else n * fact(n - 1)

на:

def fact(n):
    return 1 if(n <= 1) else n * fact(n - 1)

. Если вы пройдете 2 одинаковых номера, вы попытаетесь вычислить fact(0) (что вызовет fact(-1) и fact(-2) и т. д. до максимальной ошибки глубины рекурсии).

4
ответ дан Maxime Chéramy 28 August 2018 в 10:57
поделиться

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

Вот код для итеративной версии факторной функции:

def fact(n):
    result = 1
    for i in range(2, n + 1):
        result *= i
    return result

Обратите внимание, что Maxime говорит в предыдущем ответ, это именно то, что у вас есть: ваша функция не рассматривает факториал 0.

3
ответ дан ecampver 28 August 2018 в 10:57
поделиться
sys.setrecursionlimit(some_number)
0
ответ дан Floern 28 August 2018 в 10:57
поделиться

Ваша глубина рекурсии выходит за пределы.

  1. Рекурсия не является самым идиоматическим способом делать вещи в Python, так как у нее нет оптимизации хвоста тем самым делая нецелесообразным использование рекурсии в качестве замены итерации (даже если в вашем примере функция не является хвостовой рекурсивной, это никоим образом не поможет). В основном это означает, что вы не должны использовать его для вещей, которые имеют сложность, превышающую линейную, если вы ожидаете, что ваши входы будут большими.
  2. Если у вас есть платформа, поддерживающая более высокий предел, вы можете установить предел выше: sys.setrecursionlimit (some_number) sys.setrecursionlimit(some_number) Эта функция устанавливает максимальную глубину стека интерпретатора Python для ограничения. Этот предел предотвращает бесконечную рекурсию из-за переполнения стека C и сбой Python. Максимально возможный предел зависит от платформы. Пользователю может потребоваться установить лимит выше, когда у нее есть программа, требующая глубокой рекурсии и платформы, поддерживающей более высокий предел. Это должно быть сделано с осторожностью, потому что слишком высокий предел может привести к сбою.

ref: Ошибка рекурсивной функции Python: «превышена максимальная глубина рекурсии» Рекурсия Python max, вопрос о sys.setrecursionlimit ()

1
ответ дан hxysayhi 28 August 2018 в 10:57
поделиться

Предел рекурсии по умолчанию в версии python 3.x и далее - только 2000. Если вы вызываете ту же функцию снова и снова более 2000 раз, вы получите максимальную ошибку глубины рекурсии. Идеальным подходом было бы написать логику без рекурсии. Но если вы все еще придерживаетесь рекурсии, измените предел рекурсии по умолчанию на:

import sys

sys.setrecursionlimit (10000) # Он устанавливает предел рекурсии на 10000.

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

1
ответ дан Siva Kumar 28 August 2018 в 10:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: