1

私はしばらくこれに固執していて、Cの専門家ではありません。基本的に、既存のchar*に文字を「安全に」strcatする関数を作成しようとしています。

この例から「動的割り当て」メソッドを機能させようとしています。

Cでstrcatを使用する

いくつかの変更を加え、realloc関数によって設定されたvarを削除しました(コンパイラーはvoidを返すと言っていました)。また、文字の配列ではなく1文字だけを追加するように変更しました。これにより「realloc」パラメータが変更されると考えたので、加算文字列の長さを渡す代わりに、「sizeof(char)」を渡しました(元のサイズには余分なsizeof charが含まれていたため、x2です。ターミネータがnullであるためだと思います。 ?)

char *buffer = NULL;

int mystrcat(char addition)
{
   realloc(buffer, strlen(buffer) + sizeof(char)*2);
   if (!buffer)
     return 0;
   strcat(buffer, addition);
   return 1;
}

私はそれをこのように呼びます:

if(!safestrcat(str[i+j]))
    printf("Out of Memory");

何らかの理由で、私はこれを見ています:

myProg.exeの0x60f0d540(msvcr100d.dll)で未処理の例外:0xC0000005:アクセス違反の読み取り場所0x00000000。

そして、デバッガーは81行目にstrlen.asmを表示します。

main_loop:
    mov     eax,dword ptr [ecx]     ; read 4 bytes

これが初心者の質問である場合は申し訳ありませんが、何が起こっているのですか?加算文字がバッファに追加されないのはなぜですか?

申し訳ありませんが、正常にコンパイルされることを付け加えておきます。

4

5 に答える 5

6
  • あなたは一つの議論を忘れました
  • sizeof(char)定義上1です
  • あなたのreallocコードは壊れています
  • strcatchar2番目の引数としてを取りません
  • 新しく作成された文字列を返すだけstrcatです
char* mystrcat(char* buffer, char addition) {
    unsigned oldlen = strlen(buffer);
    buffer = realloc(buffer, oldlen + 2);
    if (buffer == NULL)
        return NULL;

    buffer[oldlen + 0] = addition;
    buffer[oldlen + 1] = '\0';
    return buffer;
}

ただし、次の2つの点に注意してください。

  1. 有効な初期化されたポインタを使用して呼び出す必要があります– !mystrcatと同じです。strcat
  2. 失敗した場合、関数は戻りますNULL–その場合、元のバッファのメモリが解放されていることを確認するのは呼び出し元の責任です。これは、関数を次のように呼び出してはならないことを意味します

    buffer = mystrcat(buffer, 'x');
    

    –これによりメモリリークが発生する可能性があります。

したがって、正しい使用法は次のようになります。

char* something = "hello";
char* buffer = malloc(sizeof(something) + 1);
strcpy(buffer, something);

char* new_buffer = mystrcat(buffer, 'x');
if (new_buffer == NULL) {
    free(buffer);
    exit(1);
}

buffer = new_buffer;

はい、複雑です。これは、安全なメモリ操作の価格です。

于 2012-05-09T16:40:48.197 に答える
2

他の回答では本当に良いアドバイスがたくさん与えられていますが、アクセス違反が発生する理由は、からbuffer始まるためNULLです。次に、あなたはしますstrlen(buffer)strlen()渡されたアドレスから始まり、に到達するまでの文字をカウントすることによって機能します'\0'。したがって、あなたの場合、初めてでは、nullポインタを逆参照します。

于 2012-05-09T17:08:56.010 に答える
2

reallocの呼び出しは完全に壊れています。成功を確認してから、関数の結果を既存のポインターに再割り当てする必要があります。

char *また、2番目のパラメータとしてstrcatではなく、に渡す必要がありますchar

変化する:

int mystrcat(char addition)
{
   realloc(buffer, strlen(buffer) + sizeof(char)*2);
   if (!buffer)
     return 0;
   strcat(buffer, addition);
   return 1;
}

に:

int mystrcat(char addition)
{
   char st[2] = { addition, '\0' };               // make temporary string to hold `addition`
   int len = buffer != NULL ? strlen(buffer) : 0; // NB: handle case where `buffer` has not yet been allocated
   char * tmp = realloc(buffer, len + 2);         // increase size of `buffer`
   if (!tmp)                                      // handle realloc failure
     return 0;
   buffer = tmp;
   strcat(buffer, st);                            // append `addition`
   return 1;
}
于 2012-05-09T16:38:27.027 に答える
1
char * mystrcat(char *str, char addition)
{
   size_t len;
   len = strlen(str);
   str = realloc(str, len + 2);
   if (!str)
     return NULL; /* ... */
   str[len++] = addition;
   str[len] = 0;
   return str;
}
于 2012-05-09T16:44:20.880 に答える
0
char *mystrcat(char *buffer, char addition) {
    char *bb;
    size_t ll;
    ll = buffer ? strlen(buffer) : 0;
    bb = realloc(buffer, ll + 2);
    if(!bb){
      fprintf(stderr, "Memory exhausted in function: mystrcat !\n");
      exit(EXIT_FAILURE);
    }
    buffer = bb; // Safe!!!
    buffer[ll] = addition;
    buffer[ll+1] = '\0';
    return buffer;
}

そんな感じ。したがって、メモリがない可能性が高い場合は、アプリケーションが終了するまで何もできません。システムだけがシャットダウンされない場合。

これは重大なエラーです。しかし、あなたはこのメッセージを見ることができます。確かにログに。不良なprtバッファーを渡した場合、正しく機能する保証はありません。たとえば、ヌルターミネータを設定するのを忘れた場合です。strlenでエラーが発生します!

于 2014-06-05T05:37:35.430 に答える