Метод Main или точка входа в программу
Если говорить простым языком, то точка входа это место, в языке c# представленное статическим методом Main, с которого начинает выполнение ваша программа при условии, что данная программа (приложение) является исполняемым, то есть будет иметь расширение (.exe).
То есть даже если ваш класс или несколько классов будут содержать 20, 30 или более разных методов, всё равно выполнение программы начинается со статического метода Main.
В вашем приложении Вы так же можете создать несколько классов и в каждый из них поместить статический метод Main, в результате ваша программа будет иметь несколько точек входа. Данный способ можно применять, например, для отладки ваших приложений при большом количестве исходного кода.
Но, тогда возникает вопрос, если точек входа несколько, тогда с какого места начнёт выполнение ваша программа?
Для примера добавим в исходный код нашей программы ещё один класс по имени Test, внутри которого поместим точно такой же статический метод Main, как в классе Program.
C#:
namespace Example
{
class Program
{
static void Main()
{
System.Console.WriteLine("метод 1");
System.Console.ReadLine();
}
}
class Test
{
static void Main()
{
System.Console.WriteLine("метод 2");
System.Console.ReadLine();
}
}
}
Если сейчас попытаться выполнить код, то компилятор выдаст ошибку:
Код:
Error Program 'E:c# projectSLLab1objx86DebugLab1.exe'
has more than one entry point defined: 'Example.Program.Main()'.
Compile with /main to specify the type that contains the entry point.
Данная ошибка возникает, потому что в программе присутствует два статических метода Main, что приводит к возникновению конфликта, если сейчас перейти в свойства текущего проекта (картинка ниже), то можно найти пункт: startup object, который по умолчанию имеет значение: Not set.
Это значит, что если ваше приложение содержит хотя бы один статический метод Main, то тогда по умолчанию данный метод и будет являться точкой входа в программу, но если в приложении несколько таких методов, как в нашем примере, то тогда необходимо явно указать точку входа в программу.
Как явно указать точку входа?
Перейдите в окно Solution Explorer и нажмите правую кнопку мыши на имени проекта, в нашем случае имя проекта Lab1. После чего в списке выберите пункт Properties, в результате должно появиться вот такое окно.
Находим пункт startup object и в выпадающем списке явно указываем класс, который будет содержать точку входа в программу. Для примера выберем Example.Test, таким образом, мы явно укажем, что в качестве точки входа в нашей программе мы будем использовать статический метод Main, который находиться в классе Test, пространства имён Example.
Если сейчас запустить нашу программу, то получим вот такой результат.
Если точка входа не найдена, то есть наша программа не будет содержать статический метод Main, или данный метод будет иметь не правильную синтаксическую конструкцию, к примеру он не будет иметь ключевое слово static, то Вы так же получите ошибку на этапе компиляции.
Читайте также:
- Создание первого приложения на языке c#. Часть вторая.
- Как найти все цифры в строке?
- Почему у меня в Data Source нет пункта Mysql Database?
The question may apply to any programming language written in Visual Studio, but I am more concerned about C++.
Is there a way to easily determine the application entry point in Visual Studio?
For a relatively small application this could be easy, but for large ones, it will be pretty hard. In my particular case I know that the project which is set as startup is the one which has the entry point, but I was unable to find it, even though the application starts and runs well.
asked Aug 17, 2016 at 15:40
meJustAndrewmeJustAndrew
5,8317 gold badges50 silver badges75 bronze badges
7
If you want to find what C++ project is executable than search for <ConfigurationType>Application</ConfigurationType>
in all your *.vcxproj
files.
If you are looking for the entry point function inside this application, than search for main
, wmain
or WinMain
functions.
Also entry point can be redefined with /ENTRY
parameter, so you can check Configuration Properties > Linker > Advanced > Entry Point
project parameter or search for /ENTRY
in your *.vcxproj
.
answered Aug 17, 2016 at 15:53
NikitaNikita
6,2502 gold badges24 silver badges37 bronze badges
2
In C++, a fully compiled program can have only one defined main
method. If there’s more than one, the compiler will complain about «multiple definitions of main» or some other similarly worded message.
So, the simplest option is to do a search for the symbol main
(or, if compiling as a Windows Subsystem program, WinMain
) and figure out which ones correspond to the «startup» project. There shouldn’t be that many, even in a relatively large solution.
answered Aug 17, 2016 at 15:53
XiremaXirema
19.7k4 gold badges31 silver badges67 bronze badges
2
When desiring to stop execution at the top of the main/WinMain function while interactively debugging a process on Windows, I typically just use F10/F11 (assuming default C/C++ key bindings in the Visual Studio IDE) to instruct the debugger to single-step (which starts the process, then performs the step, then breaks).
Note this may not always do what you want. If you want to catch global initializations, object constructions, etc, these are already done before reaching main
or WinMain
. Those require additional debugging and setting breakpoints in CRT-source code for the real global startup code (which eventually calls your main
or WinMain
). But if you simply want to break-on-main-entry for a program built with debugging symbols, this is likely the easiest way to do it.
answered Aug 17, 2016 at 16:09
WhozCraigWhozCraig
65k11 gold badges74 silver badges140 bronze badges
1
Точка входа в программу
Последнее обновление: 21.07.2021
Точка входа в программу представляет функцию, с которой начинается выполнение приложения. Для определения функции как точки входа в приложения,
применяются ряд условий:
-
Эта функция должна применять атрибут [<EntryPoint>]
-
Эта функция должна принимать один параметр — набор (а точнее массив) строк, через которые в данную функцию можно передать данные при ее вызове. (Например, при запуске приложения из командной строки)
-
Эта функция должна возвращать число типа
int
. Согласно условностям, обычно это 0 — при успешном выполнении, либо любое другое число при неудачном выполнении. -
Эта функция должна быть последней функцией в последнем компилируемом файле.
Последний компилируемый файл — это последний файл в проекте, либо последний файл в списке файлов, которые передаются компилятору при компиляции в командной строке
Как правило, эта функция называеся main, но это необязательно. Например, определим точку входа в приложение:
[<EntryPoint>] let main argv = printfn "Начало выполнения приложения" 0
Итак, данная функция применяет атрибут [<EntryPoint>]
(он указывается над определением функции). Она имеет один параметр и возвращает число.
Стоит отметить, что если параметр функции не используется, мы можем, как в общем случае, вместо него указать прочерк:
[<EntryPoint>] let main _ = printfn "Начало выполнения приложения" 0
Теперь обратимся к последнему условию: функция входа в приложение должна быть последней функций (и вообще последним опредлением в файле). То есть мы можем разместить другие конструкции,
определения значений, функций, их вызов до функции main:
let sum x y = x + y let message = "Hello F#" printfn $"{message}" [<EntryPoint>] let main _ = printfn "Функция main" 0
Но мы НЕ можем это сделать после определения функции входа в приложение:
[<EntryPoint>] let main _ = printfn "Функция main" 0 let sum x y = x + y let message = "Hello F#" printfn $"{message}"
Но в принципе в этом случае Visual Studio укажет на ошибку.
Стоит отметить, что если до функции точки входа в приложение идут вызовы других функций , то они также выполняются. В данном случае имеются ввиду
вызовы функций верхнего уровня — то есть такие вызовы функций, которые расположены вне других функций. Например, путь у нас будет следующий код программы:
let sum x y = x + y let message = "Hello F#" printfn $"{message}" printfn $"Сумма 1 и 2 равна {sum 1 2}" [<EntryPoint>] let main _ = printfn "Функция main" 0
В данном случае мы получим следующий консольный вывод:
Hello F# Сумма 1 и 2 равна 3 Функция main
Таким образом, мы видим, что все выражения, которые идут до функции main, также были выполнены.
Однако если до функции входа в приложение идут только определения функций без их вызовов, то эти функции не выполняются:
let sum x y = printfn $"Сумма {x} и {y} равна {x + y}" let printMessage _ = printfn "Hello F#" [<EntryPoint>] let main _ = printfn "Функция main" 0
Так, в данном случае будет выполняться только функция main, поскольку именно она является точкой входа в приложения. Соответственно консольный вывод программы:
Чтобы выполнить подобные функции, нам надо вызвать их в функции main:
let sum x y = printfn $"Сумма {x} и {y} равна {x + y}" let printMessage _ = printfn "Hello F#" [<EntryPoint>] let main _ = printfn "Функция main" sum 1 2 printMessage() 0
Консольный вывод программы:
Функция main Сумма 1 и 2 равна 3 Hello F#
Неявная точка входа
Выше было показано, как определять точку входа, однако в предыдущих статьях точка входа не использовалась, но код тем не менее выполнялся.
Если в коде явным образом не определено функции с атрибутом EntryPoint,
то в качестве точки входа используются все привязки значений и функций верхнего уровня, которые определены в последнем компилируемом файле.
Gouvere 19 / 19 / 8 Регистрация: 25.11.2013 Сообщений: 122 |
||||||||||||||||
1 |
||||||||||||||||
Где точка входа приложения?10.08.2014, 16:14. Показов 2905. Ответов 6 Метки нет (Все метки)
В общем, есть 3 файла. Разбирать их содержимое не нужно, меня интересует только конструкции include. Итак, файл main.cpp:
Файл Point.h:
И файл Point.cpp:
Так вот в чем проблема. Я недавно перешел с Web-программирования на системное. Там одна точка входа(например, index.php), остальные файлы просто подгружаются через include. И у меня возникает вопрос, почему это приложение из 3 файлов работает?
а он все-равно подгрузился Почему так? В Visual Studio у меня следующая картина:
0 |
87 / 68 / 19 Регистрация: 07.03.2011 Сообщений: 169 |
|
10.08.2014, 16:22 |
2 |
Сообщение было отмечено Gouvere как решение РешениеТочка входа — функция main. Связи настроил линкер, поэтому сущности, определённые в файле Point.cpp, могут использоваться в функции main. Добавлено через 1 минуту
1 |
porshe |
10.08.2014, 16:27
|
Не по теме:
при запуске собранной программы выскочит сообщение, мол, не найдена точка входа. интересно, а откуда ОС узнаёт где находится точка входа?
0 |
Убежденный Ушел с форума 16458 / 7422 / 1186 Регистрация: 02.05.2013 Сообщений: 11,617 Записей в блоге: 1 |
||||
10.08.2014, 16:30 |
4 |
|||
Сообщение было отмечено Gouvere как решение Решение
Но я нигде не писал
а он все-равно подгрузился Среда сделала это за вас:
В Visual Studio у меня следующая картина: P.S. Не по теме:
интересно, а откуда ОС узнаёт где находится точка входа? Из заголовка exe (поле называется EntryPoint, есть в спецификации
2 |
porshe |
10.08.2014, 16:32
|
Не по теме:
Из заголовка exe спасибо
0 |
Пес войны 111 / 88 / 22 Регистрация: 23.02.2012 Сообщений: 653 |
|
10.08.2014, 17:06 |
6 |
Из заголовка exe (поле называется EntryPoint, есть в спецификации все таки там функция Start указана наверное…)
0 |
19 / 19 / 8 Регистрация: 25.11.2013 Сообщений: 122 |
|
10.08.2014, 17:12 [ТС] |
7 |
Всем спасибо) Попробую собрать из командной строки)
0 |
Время чтения статьи
~2 минуты
Всем известно, что зависимости вашего проекта установлены в папке node_modules
. Но когда вы делаете require('lodash')
, как Node.js узнает, какой файл загружать при загрузке модуля?
Загрузка модуля работает в два этапа.
При загрузке зависимости Node.js работает в два этапа. Это достаточно сильно отличается от загрузки модулей, встроенных в Node.js, например, с помощью require('fs')
или локального модуля с помощью require ('./queue/mem.js')
. Зависимость загружается в два основных этапа:
— Поиск нужной директории;
— Поиск точки входа;
Поиск директории
Среда выполнения анализирует все директории, которые находятся на пути от текущего файла к корню файловой системы. В каждой директории Node.js проверяет, содержит ли она папку node_modules
. В случае, если поиск заканчивается успехом, среда выполнения переходит внутрь этой директории и ищет внутри поддиректорию, имя которой должно соответствовать имени загружаемого модуля. То есть, если мы импортируем lodash — require('lodash')
, то Node.js будет искать директорию node_modules/lodash
. Node.js будет это делать, пока не найдет совпадение.
Поиск точки входа
Найдя нужную директорию, Node.js попробует несколько стратегий для определения точки входа. Точкой входа является файл, module.exports которого возвращается в качестве значения вызова функции require()
.
Читайте также
За что могут уволить программиста: опыт и мнение экспертов: о перспективах бэкенда на JavaScript и ситуации на рынке труда.
Сначала Node.js ищет package.json файл и проверяет, содержит ли он свойство main
. Оно будет использоваться для указания на файл внутри директории пакета, который и будет точкой входа. Если main
не существует, то Node.js будет пытаться загрузить файлы в следующем порядке — index.js, index.json, index.node.
Приоритетность поиска:
— Если package.json содержит свойство main
;
— Если свойства main
нет, то Node будет загружать по порядку — index.js, index.json, index.node
.
Как выглядит точка входа для популярных пакетов
То, что происходит внутри пакетов, зависит от их авторов. Есть несколько способов указать точку входа в определенный пакет. Вот так это делают некоторые популярные модули npm.
При этом многие пакеты определяют свойство main
, и только некоторые оставляют его для поиска по умолчанию.
Адаптированный перевод статьи Main property in package.json defines package entry point с сайта Byte Archer by Panu Pitkamaki. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.