1

Cの参照によって文字列の配列を関数に渡す際に問題が発生します。

コンテキスト:いくつかのコマンドを使用して非常に単純なシェルを作成しようとしています。コマンドが入力されると、コマンドの各引数は文字列の配列のスロットに保存されます。コマンドの解析に使用される関数はlineParsingと呼ばれます(これのソースはありません-.oと.hしかありません)

問題の関数には次のヘッダーがあります。

void lineParsing (char **, int, char **, char **, char **, int *);

void lineParsing (char **item, int nargs, char **inputRedir, char **outputRedir, char **errorRedir, int *background);

関数の説明は次のとおりです。引数の配列(最初の引数)にリダイレクトまたはバックグラウンド実行が含まれるかどうかを指定します。

入力:1-引数の配列2-参照による引数の数:3-入力リダイレクト用のファイルの名前を配置する文字列の配列4-ファイルの名前を配置する文字列の配列出力リダイレクト5-エラーリダイレクト用のファイルの名前を配置する文字列の配列6-&が使用されている場合はバックグラウンドで1を保存し、0でない場合は

この関数を一時的なメインプログラムで次のように呼び出しています。

int main (int argc, char *argv[]){
    char **parrayArgumentos=NULL;
    int i,numargs,background;

    char *inputRedir[4]={"","","",""};
    char *outputRedir[4]={"","","",""};
    char *errorRedir[4]={"","","",""};

    parrayArgumentos = lineInput (&numargs); //Asks for command via standard input.
    printf ("You have typed in: %d arguments \n",numargs); //displays number of arguments

    i=0;
    while(i<=numargs-1){
        printf ("%s \n",parrayArgumentos[i]);
        i++;
    }

lineParsing(parrayArgumentos,numargs,inputRedir,outputRedir,errorRedir,&background);
//This call is problematic

    printf ("The command you have introduced has:\n%c for input redirection\n%c for output Redirection\n%s For error Ridirection\n%d background\n",inputRedir[0],outputRedir[0],errorRedir[0],background); 

    freeLineInput(parrayArgumentos);

    return 0;

}

これは、私が作成したmakefileを介してエラーや警告なしでコンパイルされます。

mishell: mishell.o parser64.o
    gcc mishell.o parser64.o -o mishell

mishell.o: mishell.c

clean:
    rm -f mishell.o mishell

バイナリを実行すると、lineParsingの呼び出しが発生した時点で次のエラーが発生します。

[xxxx@xxxx src]$ ./mishell 
ls -la > listoffiles
You have typed in: 4 arguments 
ls 
-la 
> 
listoffiles 
*** glibc detected *** ./mishell: free(): invalid pointer: 0x0000000000401078 ***
======= Backtrace: =========
/lib/libc.so.6(+0x784a6)[0x7f8a5f76b4a6]
./mishell[0x400d99]
./mishell[0x4007b6]
/lib/libc.so.6(__libc_start_main+0xf5)[0x7f8a5f714725]
./mishell[0x4005e9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:04 7865560                            /home/xxxxx/Desktop/xxxx/xxxx/xxxxx/src/mishell
00601000-00602000 rw-p 00001000 08:04 7865560                            /home/xxxxx/Desktop/xxxxx/xxxxx/xxxxx/src/mishell
00e25000-00e46000 rw-p 00000000 00:00 0                                  [heap]
7f8a5f4de000-7f8a5f4f3000 r-xp 00000000 08:03 1185891                    /usr/lib/libgcc_s.so.1
7f8a5f4f3000-7f8a5f6f2000 ---p 00015000 08:03 1185891                    /usr/lib/libgcc_s.so.1
7f8a5f6f2000-7f8a5f6f3000 rw-p 00014000 08:03 1185891                    /usr/lib/libgcc_s.so.1
7f8a5f6f3000-7f8a5f88e000 r-xp 00000000 08:03 2490393                    /lib/libc-2.16.so
7f8a5f88e000-7f8a5fa8d000 ---p 0019b000 08:03 2490393                    /lib/libc-2.16.so
7f8a5fa8d000-7f8a5fa91000 r--p 0019a000 08:03 2490393                    /lib/libc-2.16.so
7f8a5fa91000-7f8a5fa93000 rw-p 0019e000 08:03 2490393                    /lib/libc-2.16.so
7f8a5fa93000-7f8a5fa97000 rw-p 00000000 00:00 0 
7f8a5fa97000-7f8a5fab8000 r-xp 00000000 08:03 2490410                    /lib/ld-2.16.so
7f8a5fc8a000-7f8a5fc8d000 rw-p 00000000 00:00 0 
7f8a5fcb4000-7f8a5fcb8000 rw-p 00000000 00:00 0 
7f8a5fcb8000-7f8a5fcb9000 r--p 00021000 08:03 2490410                    /lib/ld-2.16.so
7f8a5fcb9000-7f8a5fcba000 rw-p 00022000 08:03 2490410                    /lib/ld-2.16.so
7f8a5fcba000-7f8a5fcbb000 rw-p 00000000 00:00 0 
7fff8533d000-7fff8535e000 rw-p 00000000 00:00 0                          [stack]
7fff853ff000-7fff85400000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

ArchLinux3.4.4-2-ARCHx86_64でgcc4.7.1を使用しています

なぜこれが起こっているのか誰かが知っていますか?

よろしくお願いします。

4

1 に答える 1

0

考えられる原因は、内の要素のいずれかを解放しようとした場合inputRediroutputRedirまたは要素が変更されていない場合です。文字列リテラル(空の文字列)に初期化されるため、これをに渡すことは不正です。errorRedir free()

ptrがnullポインタの場合、アクションは発生しません。それ以外の場合、引数がcalloc、malloc、またはrealloc関数によって以前に返されたポインターと一致しない場合、またはスペースがfreeまたはreallocの呼び出しによって割り当て解除された場合、動作は未定義です。

free()投機的な修正は、次の3つの配列の要素をNULLポインターに初期化することです(NULLポインターをに渡しても安全です)。

char *inputRedir[4]  = { NULL, NULL, NULL, NULL };
char *outputRedir[4] = { NULL }; /* Unspecifed initializers will */
char *errorRedir[4]  = { NULL }; /* be NULL by default.          */

(および)はであるため、printf()ステートメントのフォーマット指定子は正しくありませんが、提供されるフォーマット指定子は、タイプ:usefor 。です。inputRedir[0]outputRedir[0]char*%cchar%schar*

于 2012-08-13T15:47:14.823 に答える