2

ユーザー定義のシェルを構築しています。関数へのポインタの配列、つまり、いつでも呼び出すことができる共有ライブラリ関数でいっぱいの配列があります。

ここで typedef します

typedef void (*func_ptr)(char **);
func_ptr function;
void *pointers_to_functions[64];

ポインタを配列に配置する初期化が正しく機能していることをデバッグして確認しましたが、安全な対策のためのコードは次のとおりです...

void initialize_built_in(){
    void *handle;
    char *error;
    int i;
    for (i = 0; i < 5; i++){
        handle = dlopen(builtin_files[i], RTLD_LOCAL | RTLD_LAZY);
        if (!handle) {
            fprintf(stderr, "%s\n", dlerror());
            exit(1);
        }
        pointers_to_functions[i] = dlsym(handle, builtin_functions[i]);
        if ((error = dlerror()) != NULL) {
            fprintf(stderr, "%c\n", *error);
            exit(1);
        }

        if (dlclose(handle) < 0) {
            fprintf(stderr, "%c\n", *dlerror());
            exit(1);
         }
    }
}

これがセグフォルトが発生する場所です-関数を呼び出すと

int execute_built_in(char **argv){

    int i;
    //scan through the builtin_functions strings to find the correct index of pointers_to_functions - that is, they have the same ordering
    for (i = 0; i < sizeof(builtin_functions); i++){
        if (!strcmp(argv[0], builtin_functions[i])){
            //the index has been found
            function = pointers_to_functions[i];
            function(argv); //execute function
            return 0;
        }
    }
    return -1;
}

私の共有ライブラリは確かに argv をパラメータとして取ります - だから私はこれが問題だとは思いません。

私が言ったように、デバッグすると、ポインターの配列がアドレスで満たされていることがわかります。どういうわけか間違った住所かもしれないと思いますが、私はここでレンガの壁にいます.

何か案は?


そのため、関数呼び出しへのポインターをテストして、同じファイルで独自の関数型 (void *) を定義しました。

func_ptr function;
void *testfunction(char **);
void *pointers_to_functions[64] = {testfunction};

関数はシェルに何かを出力するだけです

次に、実行を強制するために execute_function 関数に条件を追加しました...

for (i = 0; i < sizeof(builtin_functions); i++){
        if (i == 0){
            function = pointers_to_functions[1];
            char *bleh[] = {"bleh"};
            function(bleh);
        }
        if (!strcmp(argv[0], builtin_functions[i])){
            //the index has been found
            function = pointers_to_functions[i];
            function(argv); //execute function
            return 0;
        }
    }

そしてそれは動作しますWOOHOO!

そのため、動的リンクに問題があり、表示できません。または、私の共有ライブラリで - 同じプロジェクトの別のシェルコードで動作する成功したライブラリをすでに構築しているため、これはありそうもありません。

では、動的リンクの何が問題なのですか?

共有ライブラリの例を次に示します

#include <stdio.h>
#include <unistd.h>

struct NewBuiltIn{
    char *CommandName[64];
    char *FunctionName[64];
    char *AnalyzerName[64];
};

struct NewBuiltIn pluggin_method = {{"cd", "cd", ""}};

void cd(char *argv[]) {
    if(chdir(argv[1]) < 0){
        printf("There was an error in changing your directory. Please check the path name and retry.\n");
    }
}
4

1 に答える 1

0

init 関数が間違っています:dlclose(handle)ロードしたすべてのライブラリをメモリからアンマップする a を実行すると、明らかに、呼び出す関数が飛んでしまいます。格納した関数ポインタの使用が完全に終了するまで、lib をメモリにマップしたままにしておく必要があります。

これは、segfault が発生したアドレスが実際にライブラリにマップされたセグメント (/proc/your_app_pid/maps 内) にあることを確認することで確認できます。

于 2015-11-18T16:38:55.030 に答える