C: как реализовать динамическое копирование функции? - PullRequest
0 голосов
/ 07 июля 2011

У меня есть статическая функция, которая предназначена для получения обратных вызовов в стиле C.Проводя некоторые эксперименты с многопоточными подходами, хочу попробовать способ получения обратного вызова в функции по разным адресам, но не хочу объявлять их все в коде, а скорее копировать функцию (с ее точкой входа) по другому адресу в памяти и регистрироватьэтот адрес с обратным вызовом.Также необходимо определить адрес точки входа функции в теле функции.

Есть ли возможность достичь этого с помощью C и, в частности, с помощью gcc в Linux?

Примечание: в моем случаеобратный вызов происходит с аргументом, который является уникальным по своему источнику - поэтому у меня нет проблем с распознаванием источников обратного вызова ... однако я чувствую необходимость описанного подхода для многопоточной + разветвленной среды - даже там, обратный вызов будет распознаваться либодескриптор или процесс / форк / ID потока

Редактировать: разветвление не работает: в следующем коде realme () и testme () являются общими адресами;Я думаю о -finstrument-functions, backtrace() и некоторых других шансах реализовать указатель memcpy + (см. Комментарии где-то ниже) ..

    #include <iostream>
#include <string>
// Required by for routine
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>   // Declaration for exit()
using namespace std;
int globalVariable = 2;

void realme()
{
    cout << "Testme() is at: " << __builtin_return_address(1) << std::endl;
}
void testme()
{
    realme();
}
    main()
    {
       string sIdentifier;
       int    iStackVariable = 20;
       pid_t pID = fork();
       if (pID == 0)                // child
       {
          // Code only executed by child process
          sIdentifier = "Child Process: ";
          globalVariable++;
          iStackVariable++;
        }
    else if (pID < 0)            // failed to fork
        {
        cerr << "Failed to fork" << endl;
        exit(1);
        // Throw exception
        }
        else                                   // parent
        {
          // Code only executed by parent process
          sIdentifier = "Parent Process:";
        }
        // Code executed by both parent and child.
        cout << sIdentifier;
        cout << " Global variable: " << globalVariable;
        cout << " Stack variable: "  << iStackVariable << endl;
        testme();
}

Ответы [ 2 ]

1 голос
/ 07 июля 2011

Это потребует от вас создания самоизменяющегося кода, кроме того, что он не так прост, он также дает вам огромное снижение производительности.Единственный способ смоделировать необходимый материал без особых проблем - создать какой-то макрос, который будет писать новую функцию каждый раз, когда вам нужно будет передать указатель на функцию обратного вызова, но это нужно знать во время компиляции.Может быть, макрос может генерировать функцию, основанную на определенных параметрах, для файла .c каждый раз, когда вы ссылаетесь на него.

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

1 голос
/ 07 июля 2011

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

...