4

私はこの単純なプログラムを実行していました、私が得る出力は「バスエラー」です。いくつかのデバッグステートメントを使用して、それが発生するポイントがstrcat()呼び出しであることがわかりました。

#include<stdio.h>
#include<string.h>
main()
{
char *s = "this is ";
char *s1 = "me";  
strcat(s,s1); 
printf("%s",s);
return 0;
}

MAC、64ビットOSでgccコンパイラを使用して実行します。さらに仕様を提供する必要がある場合はお知らせください。

ありがとう!

4

3 に答える 3

9

少し背景:

"this is ""me"文字列リテラルです; char それらは、それぞれ静的エクステントを持つ( C ++の) 9要素配列と3要素配列ですconst char(つまり、それらのメモリはプログラムの起動時に割り当てられ、プログラムが終了するまで保持されます)。そのメモリは、プラットフォームによっては書き込み可能である場合とできない場合があるため、文字列リテラルを変更しようとすると、未定義の動作が発生します(つまり、コンパイラは文字通り何でも実行できます)。つまり、文字列リテラルに書き込むことはできません。

を書くstrcat(s, s1);と、2つの問題が発生します。1つは、ターゲット配列が文字列リテラルであり、前述のように書き込み可能ではありません。次に、追加の文字を保持するのに十分な大きさではありません。9文字(0ターミネーターを含む)を保持できるサイズですが、11文字を格納しようとしています。これはバッファオーバーフローであり、重要な何かを壊すと悪いことにつながる可能性があります。

書き込み可能なターゲットバッファを割り当てる必要があります。いくつかの選択肢があります。

  1. 結果の文字列を保持するのに十分な大きさの配列を宣言できますが、一般に、コンパイル時に「十分な大きさ」の大きさはわかりません。

    
    char *s = "this is ";
    char *s1 = "me";
    char target[11];
    strcpy(target, s);
    strcat(target, s1);
    // alternately, sprintf(target, "%s%s", s, s1);
    

  2. C99では、実行時までサイズがわからない可変長配列(VLA)を宣言できます。

    
    char *s = "this is ";
    char *s1 = "me";
    char target[strlen(s) + strlen(s1) + 1];
    strcpy(target, s);
    strcat(target, s1);
    // alternately, sprintf(target, "%s%s", s, s1);
    

  3. mallocまたはを使用してターゲットバッファを動的に割り当てることができますcalloc(VLAとは異なり、バッファは必要に応じてサイズ変更できるため、これは実際に推奨される方法です)。

    
    char *s = "this is ";
    char *s1 = "me";
    char *target = malloc(strlen(s) + strlen(s1) + 1);
    strcpy(target, s);
    strcat(target, s1); 
    // or sprintf(target, "%s%s", s, s1);
    ...
    free(target); // when you're finished with the buffer
    

于 2011-04-19T14:15:37.573 に答える
8

"this is "および"me"は、アドレス空間の読み取り専用部分に存在する可能性のある文字列リテラルです。これらを変更しようとしないでください。

char s[] = "this is ";
char s1[] = "me";  

これにより、リテラルがスタックに確実にコピーされます。これは書き込み可能です。次に、次のstrcatがスタックバッファをオーバーフローさせますが、これも同様に悪いことです。

以下は機能します-使用することと使用strcatしないことstrncatは一般的に悪い習慣ですが。

#include <stdio.h>
#include <string.h>
int main()
{
  char s[100] = "this is ";
  char *s1 = "me";  
  strcat(s,s1); 
  printf("%s",s);
  return 0;
}
于 2011-04-19T13:34:03.790 に答える
2

Cでの文字列の動作、および文字配列と文字列リテラルの違いについて詳しく読む必要があります。

これを機能させるには、たとえば次のように書き直します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
  char s[100] = "this is ";
  char *s1 = "me";  

  strcat(s, s1); 

  printf("%s", s);

  return EXIT_SUCCESS;
}

さらにいくつかのポイント:

  1. main()を返しますint
  2. 記号EXIT_SUCCESS(from<stdlib.h>は0よりも明確です)。
  3. 引数をとらない関数はvoid、Cのように宣言する必要があります。の場合main()、空の括弧は無効です。
于 2011-04-19T13:37:47.313 に答える