Как найти точку входа в коде

Метод Main или точка входа в программу

Если говорить простым языком, то точка входа это место, в языке c# представленное статическим методом Main, с которого начинает выполнение ваша программа при условии, что данная программа (приложение) является исполняемым, то есть будет иметь расширение (.exe).

То есть даже если ваш класс или несколько классов будут содержать 20, 30 или более разных методов, всё равно выполнение программы начинается со статического метода Main.

29850

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

Но, тогда возникает вопрос, если точек входа несколько, тогда с какого места начнёт выполнение ваша программа?

Для примера добавим в исходный код нашей программы ещё один класс по имени Test, внутри которого поместим точно такой же статический метод Main, как в классе Program.

29851

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, в результате должно появиться вот такое окно.

29852

Находим пункт startup object и в выпадающем списке явно указываем класс, который будет содержать точку входа в программу. Для примера выберем Example.Test, таким образом, мы явно укажем, что в качестве точки входа в нашей программе мы будем использовать статический метод Main, который находиться в классе Test, пространства имён Example.

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

29853

Если точка входа не найдена, то есть наша программа не будет содержать статический метод 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

meJustAndrew's user avatar

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

Nikita's user avatar

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

Xirema's user avatar

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

WhozCraig's user avatar

WhozCraigWhozCraig

65k11 gold badges74 silver badges140 bronze badges

1

Точка входа в программу

Последнее обновление: 21.07.2021

Точка входа в программу представляет функцию, с которой начинается выполнение приложения. Для определения функции как точки входа в приложения,
применяются ряд условий:

  1. Эта функция должна применять атрибут [<EntryPoint>]

  2. Последний компилируемый файл — это последний файл в проекте, либо последний файл в списке файлов, которые передаются компилятору при компиляции в командной строке

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

  4. Эта функция должна возвращать число типа int. Согласно условностям, обычно это 0 — при успешном выполнении, либо любое другое число при неудачном выполнении.

  5. Эта функция должна быть последней функцией в последнем компилируемом файле.

Как правило, эта функция называеся 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:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cstdlib>
#include "Point.h"
 
using namespace std;
 
int main() {
    Point p;
    
    p.setX(42);
    p.setY(-123);
 
    cout << "x = " << p.getX() << ", y = " << p.getY();
 
    system("pause");
 
    return 0;
}

Файл Point.h:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef POINT_H
#define POINT_H
 
class Point {
public:
    int getX() { return x; }
    int getY() { return y; }
    void setX(int);
    void setY(int);
private:
    int x, y;
};
 
#endif

И файл Point.cpp:

C++
1
2
3
4
5
6
7
8
9
10
11
// Реализация класса Point
 
#include "Point.h"
 
void Point::setX(int new_x) {
    x = (new_x >= 0) ? new_x : 0;
}
 
void Point::setY(int new_y) {
    y = (new_y >= 0) ? new_y : 0;
}

Так вот в чем проблема. Я недавно перешел с Web-программирования на системное. Там одна точка входа(например, index.php), остальные файлы просто подгружаются через include. И у меня возникает вопрос, почему это приложение из 3 файлов работает?
Я так понимаю, файл в котором определена функция main() и является точкой входа. Но я нигде не писал

C++
1
include "Point.cpp"

а он все-равно подгрузился

Почему так?

В Visual Studio у меня следующая картина:
Заголовочные файлы: Point.h
Файлы исходного кода: main.cpp, Point.cpp



0



87 / 68 / 19

Регистрация: 07.03.2011

Сообщений: 169

10.08.2014, 16:22

2

Лучший ответ Сообщение было отмечено Gouvere как решение

Решение

Точка входа — функция main. Связи настроил линкер, поэтому сущности, определённые в файле Point.cpp, могут использоваться в функции main.

Добавлено через 1 минуту
Вы попробуйте вместо функции main дать ей другое название. Компилятор, скорее всего, выдаст сообщение об ошибке. Хотя, может быть он ничего и не скажет, но при запуске собранной программы выскочит сообщение, мол, не найдена точка входа.



1



porshe

10.08.2014, 16:27

Не по теме:

Цитата
Сообщение от Чумаков Антон
Посмотреть сообщение

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

интересно, а откуда ОС узнаёт где находится точка входа?



0



Убежденный

Ушел с форума

Эксперт С++

16458 / 7422 / 1186

Регистрация: 02.05.2013

Сообщений: 11,617

Записей в блоге: 1

10.08.2014, 16:30

4

Лучший ответ Сообщение было отмечено Gouvere как решение

Решение

Цитата
Сообщение от Gouvere
Посмотреть сообщение

Но я нигде не писал

C++
1
include "Point.cpp"

а он все-равно подгрузился
Почему так?

Среда сделала это за вас:

Цитата
Сообщение от Gouvere
Посмотреть сообщение

В Visual Studio у меня следующая картина:
Заголовочные файлы: Point.h
Файлы исходного кода: main.cpp, Point.cpp

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

Не по теме:

Цитата
Сообщение от porshe
Посмотреть сообщение

интересно, а откуда ОС узнаёт где находится точка входа?

Из заголовка exe (поле называется EntryPoint, есть в спецификации
формата исполняемых файлов — PE).



2



porshe

10.08.2014, 16:32

Не по теме:

Цитата
Сообщение от Убежденный
Посмотреть сообщение

Из заголовка exe

спасибо



0



Пес войны

111 / 88 / 22

Регистрация: 23.02.2012

Сообщений: 653

10.08.2014, 17:06

6

Цитата
Сообщение от Убежденный
Посмотреть сообщение

Из заголовка exe (поле называется EntryPoint, есть в спецификации
формата исполняемых файлов — PE).

все таки там функция Start указана наверное…)



0



19 / 19 / 8

Регистрация: 25.11.2013

Сообщений: 122

10.08.2014, 17:12

 [ТС]

7

Всем спасибо) Попробую собрать из командной строки)



0






Время чтения статьи
~2 минуты

Разбираем Node.js. Как свойство main в package.json определяет точку входа главное изображение

Всем известно, что зависимости вашего проекта установлены в папке 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, и только некоторые оставляют его для поиска по умолчанию.


Адаптированный перевод статьи Main property in package.json defines package entry point с сайта Byte Archer by Panu Pitkamaki. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.

Понравилась статья? Поделить с друзьями:
  • Невкусные пельмени как исправить
  • Как найти кнопку интернет
  • Как найти движение на конец года
  • Как найти общий запас
  • Как можно найти человека в архиве