Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Затраты на вызов функций

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

То есть образно говоря что лучше 10000 строк кода без функций или 6000 - с функциями.

Заранее спасибо.
Ответ:
Сообщение от Denis_prophet
Так никто и не ответил на поставленный вопрос...
Создай новую тему и задай вопрос. Это будет намного эффективнее чем поднимать тему трёхлетней давности.

Добавлено через 6 минут
Сообщение от miriganua
Тратится ли время и вообще "средства" компьютера на вызов функций?
А вообще ответ - да. Тратятся.
Вопрос: Вызов функции другого процесса (неверные регистры)

Всем привет. Я пытаюсь вызвать функцию из другого процесса, но вот беда - регистры формируются не те, из-за чего вызов функции происходит (отслеживаю через Cheat Engine debugger), но не делается то, что должно.
Что именно я делаю:
1. создаю CLRHost.dll, которую инжектирю через CheatEngine в приложение Wow-64.exe
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <Windows.h>
 
#include <metahost.h>
//#include <mscoree.h>
#include <string>
 
#pragma comment(lib, "mscoree.lib")
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
 
DWORD WINAPI StartTheDotNetRuntime(LPVOID lpParameter)
{
    ICLRMetaHost *lpMetaHost = NULL;
    HRESULT hr;
 
    // выделяем адрессное пространство
    hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID *)&lpMetaHost);
    if (FAILED(hr)) return 1;
 
    DWORD dwVersion = 0;
    DWORD dwImageVersion = 0;
    ICLRRuntimeInfo * lpRuntimeInfo = NULL;
    // получаем информацию о CLR .NET
    hr = lpMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&lpRuntimeInfo);
    if (FAILED(hr)) return 2;
 
    ICLRRuntimeHost * lpRuntimeHost = NULL;
    // загружаем среду CLR
    hr = lpRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&lpRuntimeHost);
    if (FAILED(hr)) return 3;
 
    // запускаем CLR, используя CLR 4 версии
    hr = lpRuntimeHost->Start();
    if (FAILED(hr)) return 4;
 
    LPWSTR strDLLPath = new WCHAR[_MAX_PATH];
    ::GetModuleFileNameW((HINSTANCE)&__ImageBase, strDLLPath, _MAX_PATH);
 
    std::wstring tempPath = strDLLPath;
    INT64 index = tempPath.rfind('\\'); // последние символы в пути ""
    tempPath.erase(index, tempPath.length() - index); // удаляем все символы спереди, получается только имя
    tempPath += L"\\DomainManager.dll";
 
    DWORD dwRetCode = 0;
    // переходим в менеджер доменов и создаем домен для нашего приложения
    hr = lpRuntimeHost->ExecuteInDefaultAppDomain((LPWSTR)tempPath.c_str(), L"DomainManager.EntryPoint", L"Main", L"TestExecude.exe", &dwRetCode);
    if (FAILED(hr)) return 5;
 
    return 0;
}
 
BOOL APIENTRY DllMain(HINSTANCE hInts, DWORD reason, LPVOID reserved)
{
    switch (reason)
    {
    case DLL_PROCESS_ATTACH:
    {
        DWORD dwThread;
        // создаем поток с указанием функции для выполнения StartTheDotNetRuntime
        HANDLE hThread = CreateThread(0, 0, StartTheDotNetRuntime, NULL, 0, &dwThread);
    }
    case DLL_PROCESS_DETACH:
    {
 
    }
    }
    return true;
}

2. создается домен приложения в DomainManager
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
 
namespace DomainManager
{
    public interface IAssemblyLoader
    {
        void LoadAndRun(string file);
    }
 
    public class EntryPoint
    {
        [DllImport("User32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);
 
        [STAThread]
        public static int Main(string args)
        {
            bool firstLoaded = false;
            while (true)
            {
                if (!firstLoaded)
                {
                    firstLoaded = true;
                    new CleanDomain(args);
                }
 
                if ((GetAsyncKeyState(Keys.F11) & 1) == 1)
                {
                    new CleanDomain(args);
                }
 
                Thread.Sleep(10);
            }
            return 0;
        }
    }
 
    public static class DomainManager
    {
        public static AppDomain CurrentDomain { get; set; }
        public static CleanAssemblyLoader CurrentAssemblyLoader { get; set; }
    }
 
    public class CleanAssemblyLoader : MarshalByRefObject, IAssemblyLoader
    {
        public CleanAssemblyLoader()
        {
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }
 
        #region IAssemblyLoader Members
 
        public void LoadAndRun(string file)
        {
            Assembly asm = Assembly.Load(file);
            MethodInfo entry = asm.EntryPoint;
            //object o = asm.CreateInstance(entry.Name);
            entry.Invoke(null, new object[] {null});
        }
 
        #endregion
 
        private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            if (args.Name == Assembly.GetExecutingAssembly().FullName)
                return Assembly.GetExecutingAssembly();
 
            string appDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string shortAsmName = Path.GetFileName(args.Name);
            string fileName = Path.Combine(appDir, shortAsmName);
 
            if (File.Exists(fileName))
            {
                return Assembly.LoadFrom(fileName);
            }
            return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null;
        }
    }
 
    /// <summary> 
    /// The actual domain object we'll be using to load and run the Onyx binaries.
    /// </summary>
    public class CleanDomain
    {
        private readonly Random _rand = new Random();
        public CleanDomain(string assemblyName)
        {
            try
            {
                string appBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                var ads = new AppDomainSetup { ApplicationBase = appBase, PrivateBinPath = appBase };
                DomainManager.CurrentDomain = AppDomain.CreateDomain("CleanDomain_Internal_" + _rand.Next(0, 100000),
                                                                     null, ads);
                AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
                DomainManager.CurrentAssemblyLoader =
                    (CleanAssemblyLoader)
                    DomainManager.CurrentDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName,
                                                               typeof(CleanAssemblyLoader).FullName);
                //System.Windows.Forms.MessageBox.Show(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), assemblyName));
                
                DomainManager.CurrentAssemblyLoader.LoadAndRun(
                    Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), assemblyName));
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
            finally
            {
                DomainManager.CurrentAssemblyLoader = null;
                AppDomain.Unload(DomainManager.CurrentDomain);
            }
        }
 
        Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            try
            {
                Assembly assembly = System.Reflection.Assembly.Load(args.Name);
                if (assembly != null)
                    return assembly;
            }
            catch
            {
                // ignore load error 
            }
 
            // *** Try to load by filename - split out the filename of the full assembly name
            // *** and append the base path of the original assembly (ie. look in the same dir)
            // *** NOTE: this doesn't account for special search paths but then that never
            //           worked before either.
            string[] Parts = args.Name.Split(',');
            string File = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "" + Parts[0].Trim() + ".dll";
 
            return System.Reflection.Assembly.LoadFrom(File);
        }
    }
}

3. Вызываю функцию через delegat.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
namespace TestExecude
{
    static class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Int64 CastSpellOffset = 0x45C9F0; //0x45DE0B;
            Int64 address = Process.GetProcessesByName("Wow-64")[0].MainModule.BaseAddress.ToInt64() + CastSpellOffset;
            CastSpellByID Cast = (CastSpellByID)Marshal.GetDelegateForFunctionPointer(new IntPtr(address), typeof(CastSpellByID));
            Cast(19434, 0, new byte[16], 0, 0, 0, 0);
        }
 
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        delegate Int64 CastSpellByID(UInt64 spellId, Int64 itemId, byte[] guid, Int64 isTrade, Int64 a6, Int64 a7, Int64 a8);
    }
}

Что такое CastSpellByID? Эта функция, которая находится по адресу Wow-64.exe + CastSpellOffset (0x45C9F0). Если смотреть через IDA, то она находится по адресу 14045C9F0. А Cast(19434, 0, new byte[16], 0, 0, 0, 0); 19434 - это .
С введением разобрались, теперь к проблеме. Перед тем, как проверить свою программу, я ставлю брейкпойнт в CheatEngine на функцию каста по адресу упомянутом выше Wow-64.exe + 45C9F0. Вызов функции происходит! но, значения регистров не там, где они должны быть.

Как показано на картинке, 1-вые значения регистров стандартные (т.е. вызывается непосредственно из игры). Наш будет выглядеть, как 19434 dec = 4BEA hex. Отсюда видно, что ID заклинания находится в регистрах RDX и RBP.
На 2 картинке уже непосредственно мой вызов через инжект функции Cast(19434) и без лишних переменных, объявленный делегат при этом delegate Int64 CastSpellByID(UInt64 spellId);
На 3 картинке уже вызов Cast(19434, 0, new byte[16], 0, 0, 0, 0); (взято из другого, старого, уже не рабочего проекта) и delegate Int64 CastSpellByID(UInt64 spellId, Int64 itemId, byte[] guid, Int64 isTrade, Int64 a6, Int64 a7, Int64 a8).
Как видно во 2 и 3 случае ID заклинания 4BEA находится в регистре RCX, из-за чего происходит последующий вызов на несуществующий адрес другой функции.

Что можете посоветовать?
Ответ: Решил пока посмотреть другие функции, что вызывают Spell_C_CastSpell. Эти функции очень похожи на перегрузки. Поэтому, я постараюсь найти ту, у которой значения мне уже известны: pPlayer, GUID, pTarget и другие. Я нашел их всех, теперь буду смотреть по Hex-rays.
Вопрос: Неясный вызов функции

Имеются две функции
C++
1
2
3
4
5
6
7
8
9
10
11
void may(char a) {
    using std::cout;
    using std::endl;
    cout << "void may char a" << endl;
}
 
void may(const char &a) {
    using std::cout;
    using std::endl;
    cout << "void may const char &a" << endl;
}
И вызов
C++
1
may('B');
В результате неоднозначный вызов функции. Я не могу понять почему void may(const char &a) является однозначным void may(char a), ведь вызов may('B') передает значение, даже не переменную. Объясните пожалуйста
Ответ: В вызове may('B'); аргумент есть rvalue. Константная ссылка может быть связана с rvalue, т.е. подходит вторая версия функции. Но одновременно подходит и первая версия, т.к. rvalue может быть передано по значению. Если хочется избежать неоднозначности - можно убрать const. Обычная ссылка не может быть связана с rvalue, и будет вызвана первая версия.
Вопрос: Вызов функции WinAPI в ассемблерной вставке

Доброго времени суток! Необходимо получить значение времени вызовом функции WinAPI в ассемблерной вставке. Программа компилируется, но когда доходит до вызова функции выдается сообщение об ошибке следующего рода:
"Вызвано исключение по адресу 0x750DE804 (KernelBase.dll) в simple.exe: 0xC0000005: нарушение прав доступа при записи по адресу 0xCCCCCCCC."

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <Windows.h>
#include <iostream>
 
int main()
{
    SYSTEMTIME t;
 
    __asm
    {
        push t
        call GetLocalTime
    }
 
    system("pause");
}
Пробовал с другой функцией (Sleep), и все отлично работало. Кто-нибудь может сказать в чем ошибка/проблема?
Ответ: Функции GetLocalTime нужен адрес структуры SYSTEMTIME, а не сама структура.
Вопрос: Вызов функции в контроле кнопкой с формы

И снова здравствуйте Я делаю мастер настройки подключения к базе данных для своего приложения. Решил сделать на 1-й форме, меняя контролы. Но столкнулся с проблемой, на нажатие кнопки "далее" должен сработать обработчик, но кнопка далее - одна для всего мастера, и загромождать ее кодом совсем не хочется. Возможно ли сделать вызов функции в контроле кнопкой с формы?
Ответ: danyasworld,
тогда не
C#
1
2
3
4
public void worker()
{
 //...
}
а
C#
1
2
3
4
5
public тип_результата_работы worker() // например, public string worker()
{
 //...
 return rezult; //метод возвращает в точку вызова значение rezult
}
а при вызове:
C#
1
тип_результата_работы имя_переменной = (pages[i] as page1).worker();
например
C#
1
string rez = (pages[i] as page1).worker();
Вопрос: Как можно сжать данный код, вызов функции?

PHP
1
2
3
4
5
6
7
 if ( isset($get['q']) && $get['q'] == 2) { 
                 $data["result"] = $this->functions->question2();
            } else if ( isset($get['q']) && $get['q'] == 3) { 
                 $data["result"] = $this->functions->question3();
            } else if ( isset($get['q']) && $get['q'] == 4) { 
                 $data["result"] = $this->functions->question4();
            }
Можно ли вызов функции записать так:
PHP
1
question$$get[;q'();
или так:
PHP
1
question.$get['q']();]
Ответ:
Сообщение от Para bellum
P.S. Но мне подобная проверка не нравится.
Я подумал и увидел, что тут тоже есть "грешки", например что будет если $get['q'] = 3.5 понятное дело, что произойдет вызов метода question3.5(), что не есть гуд, это так то тоже желательно учесть, думаю это дело делать так придется:
PHP
1
($get['q'] == 2 || $get['q'] == 3 || $get['q'] == 4)
ну или через
PHP
1
case()
если параметров больше будет, при необходимости запихать в функцию, в которой как вариант сравнивать $get['q'] с массивом значений
PHP
1
array (2, 3, 4, ...)
Вопрос: При вызове функции выдает ошибку

При вызове функции выдает ошибку... >>> Constructor TemplateCore::TemplateCore() cannot be static in /sata1/home/users/3dom/www/components/TemplateCore.php on line 13.... вроде правильно вызываю... подскажите в чем дело..

PHP
1
2
3
4
5
6
7
class TemplateCore
{
    public static function TemplateCore()
    {
 
    }
}
PHP
1
2
3
4
5
6
7
class AutoIncludeContent
{
    public static function getAutoIncludeContent()
    {
       TemplateCore::TemplateCore();
    }
}
Добавлено через 25 минут
подскажите где собака... удалил из кода все кроме функций... кто понимает почему...
Ответ: Если вы называете функцию метод таким же именем, как и название класса, этот метод считается конструктором, поэтому не может быть статическим.
Вопрос: Error: Слишком мало аргументов в вызове функции

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <math.h>
float s_tr(float ax, float ay, float bx, float by, float cx, float cy, float dx, float dy) 
{
    float S;
    S = fabs((bx-ax)*(ay+by)+(cx-bx)*(cy+by)+(ax-cx)*(cy+ay))/2;
    return S;
}
float stor(float ax, float ay, float bx, float by, float cx, float cy, float dx, float dy)
{
    float st;
    st=fabs(sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay)));
    return st;
}
float dlin( float s, float s2, float s3, float ab, float bc, float ac)
{
    float h;
    h=2*s/ab;
    return h; 
}
int main()
{
float ax,  ay,  bx,  by,  cx,  cy,  dx,  dy;
float s, s2, s3;
float ab, bc, ac;
float da, db, dc;
scanf ("%f %f %f %f %f %f %f %f", &ax,  &ay,  &bx,  &by,  &cx, &cy,  &dx,  &dy);
s=s_tr(ax,  ay,  dx,  dy,  bx,  by);
s2=s_tr(bx, by, dx, dy, cx, cy);
s3=s_tr(cx, cy, dx, dy, ax, ay); 
 
ab=stor(ax, ay, bx, by);
bc=stor(bx, bc, cx, cy);
ac=stor(ax, ay, cx, cy);
 
da=(s, ab);
db=(s2, bc);
dc=(s3, ac);
 
if (da<db && dc)
    printf ("%4.f", da);
else
    if (db< da && dc)
        printf ("%4.f", db);
    else
        printf ("%4.f", dc);
return 0;
}
Даны координаты вершин треугольника, координаты точки D, лежащей внутри треуголь-
ника, требуется найти и вывести наименьшее из расстояний от точки D до какой-либо из сторон
треугольника.

s=s_tr(ax, ay, dx, dy, bx, by);
s2=s_tr(bx, by, dx, dy, cx, cy);
s3=s_tr(cx, cy, dx, dy, ax, ay);

ab=stor(ax, ay, bx, by);
bc=stor(bx, bc, cx, cy);
ac=stor(ax, ay, cx, cy);

da=(s, ab);
db=(s2, bc);
dc=(s3, ac);
После этих строк пишет слишком мало аргументов в вызове функции
Ответ: слишком мало - надо добавить
сколько в скобках прототипа - столько в скобках вызова, андерстенд?
Вопрос: слишком много аргументов в вызове функции или как создать много файлов на рабочем столе

Мне нужно создать на рабочем столе очень много файлов вот команда для создания 1 файла

wchar_t szBuf[MAX_PATH]{ 0 };
GetEnvironmentVariableW(L"USERPROFI LE", szBuf, MAX_PATH);
wcscat(szBuf, L"\\Desktop\\1234567 open 11");
CreateDirectoryW(szBuf, NULL);

но мне надо много

GetEnvironmentVariableW(L"USERPROFI LE", szBuf, MAX_PATH);
wcscat(szBuf, L"\\Desktop\\by EM %a", &a);
CreateDirectoryW(szBuf, NULL);
при использавании этого кода вылезает ошибка слишком много аргументов в вызове функции
помогите создать много файлов на рабочем столе
Ответ: Не файл, а папку...

По теме: хотя бы прочитайте, что делает функции и сколько параметров. wcscat принимает только 2 параметра. Вам надо что-то из семейства wsprintf или более правильно собирать строку.
Вопрос: Передача переменных при вызове функции между модулями

Здравствуйте.
Переводится программа с VCL формой из Delphi в С++.
В главное модуле VCL форма, во втором модуле Unit без формы.
В главном модуле (pas) определяются переменные, объявленные во втором модуле, и вызывается функция из второго модуля без параметров, однако переменные всё же передаются.
Вызов функции происходит в процедуре AppIdle до определённого момента по условию (if параметр = true then Done = false).
В Delphi после вызова функции происходит выполнение функции во втором модуле, после завершения выполнения происходит возврат в процедуру AppIdle, однако переменные, изменённые во втором модуле, сохраняют свои значения.

При переводе в С++ в аналогичной функции AppIdle при вызове функции в главном модуле с VCL формой (cpp) без параметров переменные не передаются во второй модуль Unit (cpp) и при вызове функции никакие переменные не изменяются при присваивании.
Если указать в параметрах вызываемой функции переменные - они передаются в функцию и значения изменяются, однако при завершении выполнения вызываемой функции переменные не сохраняют свои изменённые значения.
После возврата в главный модуль и вызове повторно функции из второго модуля передаются стартовые значения, а не изменённые.

Объявление в главном модуле переменных extern не помогает (возможно неверно).
Каким образом в С++ организовать передачу параметров функции между модулями аналогично Delphi?

Если нужно будет предоставлю код и уточню детали.
Заранее спасибо.
Ответ:
Сообщение от volvo
Нет, в хидере оставить с extern-ом, а в cpp - без него. Таким образом, линкер разберется, что ты от него хочешь, и свяжет extern-описания с переменными, описанными в модуле RungKut. А поскольку они в хидере описаны как внешние - то и из First.cpp к ним будет доступ.
Сообщение от BIOSonar7
в С++ параметры во второй модуль не передаются
Сделаешь правильно то, что написано выше - все будет передаваться. Ты ж с несколькими формами в проекте можешь работать? Вот и посмотри, как описывается и как определяется переменная Form1 в хидере и в cpp-файле. Точно то же самое я предлагаю тебе сделать со всеми твоими переменными. Извини, полностью проект переводить не буду, ибо нестандартными компонентами не пользуюсь, а они у тебя есть...
Да, действительно. Огромное спасибо. Некоторые параметры неверно рассчитываются, но это уже другая история, буду разбираться

Добавлено через 6 часов 42 минуты
Разобрался и с параметрами. Действительно ключевое это объявление переменных через extern в header файле и дубль объявления переменных без extern в cpp файле.