2
main(){
   char *cmd1[20] = {NULL};
   int x = parse_command(cmd1);
   printf("%s\ ",cmd1[0]);
}

parse_command(char *inTempString){
   char tempString[256];
   (call to function that assigns a string to tempString)
   cmd1[0] = tempString;
}

cmd1[0]内の印刷時に問題がありますmain。私はそれがダングリングポインターエラーであることを確信しています。私はそれを修正する方法を本当に知りません。

4

5 に答える 5

4

プログラムには 2 つの問題があります。

まず、あなたが言うとき:

char *cmd1[20] = {NULL};

cmd1への 20 個のポインターの配列ですchar。これはcmd1[i]for iin [0,20) が へのポインタであることを意味しますchar

C には、配列を関数に渡すと、配列の最初の要素へのポインターのみが関数に渡されるという規則があります。つまり、次のようなコードがある場合:

int ai[20];
f(ai);

ai関数呼び出しの の型はf(ai);int *あり、 に渡されるポインタはの最初の要素である にf()等しいです。&ai[0]ai

だから、あなたがするとき:

parse_command(cmd1);

parse_command()に渡される「もの」 &cmd1[0]、つまり の最初の要素へのポインタであることがすぐにわかりますcmd1cmd1[0]は 型なので、 に aをchar *渡しています。したがって、あなたの宣言:char **parse_command

parse_command(char *inTempString);

間違っている場合は、次のことを行う必要があります。

parse_command(char **inTempString);

あなたの呼び出しに合わせて。parse_command()これは、が の複数の値を解析することを前提としていcmd1ます。その場合は、要素の数も に渡す必要がありますcmd1。これは、要素の数がparse_commnd()わからないためcmd1です。

2 番目の問題は、C の関数からローカル変数のアドレスを返すことができないことです。上記のように、関数呼び出しに加えて、C で配列を返すか、C で配列に何かを割り当てることでも名前が付けられます。配列の最初の要素へのポインタへの「崩壊」。

あなたの機能を考えると:

/* changed inTempString to cmd1 because that's what you probably meant */
int parse_command(char *cmd1)
{
    char tempString[256];
    /* call to function that assigns a string to tempString */
    cmd1[0] = tempString;
    /* you need to return an int from here */
}

へのtempString代入のcmd1[0]は、実際には&tempString[0]、つまり の最初の要素へのポインタですtempString。ただしtempString、関数が戻るとすぐに破棄されるため、ポインターは無効になります。後で値を使用することはできません。

実際、C では、配列の名前は、次の場合を除いて、すべての場合に最初の要素へのポインターに減衰します。

  • 演算子のオペランドとして使用される場合sizeof、および
  • &アドレスオブ ( ) 演算子のオペランドとして使用する場合

より正確に言うと、オブジェクト コンテキストでは配列の名前はポインターに分解されず、値コンテキストではポインターに分解されます。詳しくはこちらをご覧ください。

では、2 番目の問題をどのように修正すればよいでしょうか。それは依存します — でメモリを動的にparse_command()割り当てて、そのメモリを に割り当てるcmd1[0]か、関数で作成することができtempString staticます。static関数が戻ったときに関数内の変数は破棄されないため、変数へのポインターを引き続き使用できます。動的割り当てはより多くの作業です。割り当ての失敗を心配する必要があり、完了したらポインターを解放することを忘れないでください。 array の方が簡単ですが、別の呼び出しにより配列が上書きされ、一般性が低下するstaticため、注意が必要です。parse_command

「動的メモリ」ルートに進みたいと仮定すると、使用できるスキームは次のとおりです。

#include <stdio.h> /* printf */
#include <stdlib.h> /* malloc and free */

int main(void) /* main returns int */
{
    char *cmd1[20] = {NULL};
    /* number of commands.  "sizeof cmd1" is the number of bytes
       used by the cmd1 array, and "sizeof cmd1[0]" is the number
       of bytes used by one element of the array.  The division
       gives you the number of elements.  This is 20 of course
       but doing it this way makes sure that changing "20" to any
       number works. */
    size_t ncmds = sizeof cmd1 / sizeof cmd1[0];
    /* pass the number of commands to "parse_command", since
       it can't know otherwise */
    int x = parse_command(cmd1, ncmds);
    int i;
    for (i=0; i < x; ++i) {
        printf("%s ", cmd1[i]);
        free(cmd1[i]);
    }
    return 0; /* return a value from main */
}

int parse_command(char **cmd1, size_t ncmds)
{
    char *tempString; /* we will malloc this */
    int i; /* the number of mallocs done successfully */
    tempString = malloc(...);
    if (tempString == NULL) {
    /* failure, handle gracefully */
    } else {
        ++i; /* make sure i doesn't exceed or equal ncmds */
    }
    cmd1[0] = tempString;
    /* do the above as many times as you need */
    return i; /* the number successfully assigned to */
}
于 2010-03-02T03:24:00.813 に答える
0

次のようなものが機能します。

parse_command(char **inTempString){
        static char tempString[256];
        strcpy(tempString,"some string you want to copy");
        inTempString[0] = tempString;
}
  • あなたのコードでは、関数が戻ると tempString は存在しません。関数が戻った後でも、それを維持する必要があります。スペースを動的に割り当てて後で割り当てを解除するか、静的として宣言することができます。
  • また、型引数 inTempString を char* から char** に変更する必要があります。
于 2010-03-02T02:58:15.160 に答える
0

から関数cmd1内にある変数にアクセスしようとしています。mainparse_command

そのメソッド内で宣言されていないため、少なくともcmd1[0]will は整数のように見えると思います。

cmd1として宣言されてarray of char*いますが、メソッドへのパラメーターはchar*である可能性がありますが、 ではない可能性がありpointer to char arrayます。 pointer to array of char*

char 配列を別の char 配列にコピーする最良の方法は、 を使用するかmemcpystrcpyコピーする src、dest、および size へのポインターを受け入れる同様のメソッドを使用することです。

于 2010-03-02T02:58:31.613 に答える