2016-09-15 1 views
0

私はJavaプログラマで、Cを拾うのに苦労しています。特に、strcat()を理解するのに苦労しています。私が電話した場合:strcatはソース文字列を上書きしますか?

strcat(dst, src); 

私はstrcat()が自分のdst文字列を変更することになります。 src文字列だけを残してはいけませんか? GCCでコンパイル、

私のLinuxボックスに、この出力を生成
#include<stdio.h> 
#include<string.h> 

void printStuff(char* a, char* b){ 
     printf("----------------------------------------------\n"); 
     printf("src: (%d chars)\t\"%s\"\n",strlen(a),a); 
     printf("dst: (%d chars)\t\"%s\"\n",strlen(b),b); 
     printf("----------------------------------------------\n"); 
} 

int main() 
{ 
     char src[25], dst[25]; 
     strcpy(src, "This is source123"); 
     strcpy(dst, "This is destination"); 

     printStuff(src, dst); 
     strcat(dst, src); 
     printStuff(src, dst); 

     return 0; 
} 

:以下のコードを考えてみましょう

---------------------------------------------- 
src: (17 chars) "This is source123" 
dst: (19 chars) "This is destination" 
---------------------------------------------- 
---------------------------------------------- 
src: (4 chars) "e123" 
dst: (36 chars) "This is destinationThis is source123" 
---------------------------------------------- 

私は完全な「これはsource123される」文字列がメモリに残っていると仮定していますstrcat()は、char * srcポインタを13文字分進めました。しかし、なぜ?なぜ13文字ですか?私はdst文字列の長さで遊んだし、strcat()が完了した後は必ずsrcポインタに影響を与えます。しかし、私は理由を理解していません...

また... GDBでこれをデバッグする方法は?私はstrcat()関数にステップするために "ステップ"を試みましたが、その関数はデバッガによって解析されなかったと思います。 "ステップ"は何もしなかった。

ありがとうございます! -ROA

PS - このサイトの同様のstrcat()記事を読みましたが、私の質問に直接当てはまるようなものは見当たりませんでした。私がポストを見逃した場合は謝罪しました。

+1

"これは完全なものです"これはsource123 "文字列がまだメモリに残っている" - >多分です。コードがサンドボックスの外部で実行されると(配列の境界外に書き込む)、未定義の動作(UB)が発生する可能性があります。期待しないでください。 "しかし、src文字列だけを残してはいけませんか?"今日の結果と説明は意味をなさないかもしれませんが、明日の結果は異なるかもしれません。 – chux

+1

あなたは 'dst'に対して' char [25] 'しか割り当てませんでした。あなたはそこに37文字を入れる(後のヌルを含む)とどのように期待しますか? – user2357112

+1

'src' +' dst'に 'dst [25]'で割り当てられた24 + 1ターミネーター文字よりも多くの文字列があります –

答えて

4

宛先に新しい連結文字列を保持するのに十分なメモリが割り当てられていません。この場合、srcがおそらくstrcatによって上書きされているのは、dstの境界を越えて書き込まれているためです。

dstに十分なメモリを割り当てます。ソース文字列を上書きすることなく動作するはずです。 連結された文字列を保持する新しいメモリセグメントは、少なくとも2つの文字列(ケース36の場合)とnull終端文字のスペースのサイズ以上である必要があることに注意してください。

+4

は、この種のバグは非常に一般的なセキュリティ上の問題であり、['strncat'](http://en.cppreference.com/w/c/string/byte/strncat)自体は...セキュリティ人々が期待しているように行動しないので問題になる。 – Mgetz

+1

@Mgetz strncatは期待通りに動作します。おそらくstrncpyと混同していますか? – hyde

+1

@hyde、私は、 'strncat()'に渡された長さパラメータが、宛先バッファの合計サイズを表していると思う傾向があると思います。代わりに、転送する文字数の上限を表すことは驚くべきことではなく、使いにくいことです。 –

1

はい、あなたのバックグラウンドが厳密にJavaの場合、手動でメモリ管理を行うには何らかの問題があります。

Cの文字列に関連するものに関しては、Java Stringについてあなたが知っているすべてをあなたの頭の中に置くことはおそらく役に立ちます。 Cの文字列の最も近いJava類似体はchar[]byte[]です。しかし、そこでさえ、Javaはあなたのために境界チェックを実行するので、問題になる可能性がありますが、Cはそうではありません。実際には、Cはあなたがしなければならないことのすべてのやり方をすることを可能にします。特に

、あなたがstrcat()またはchar配列に書き込む他の関数を呼び出し、あなたがは、文字に対応するために先の配列に十分なスペースがあることを確実にする責任があります。存在しない場合、結果の動作は定義されていません(誰がを知っていますか?が発生します)。あなたはそのような未定義の行為を行使しました。

一般的に言えば、あなたはこれらのものの一つ以上実行する必要があります。少なくともそのくらいのスペースを

  • が必要になることができたサイズのハード上限を持っているし、そして割り当てる、または
  • ノウあなたが持っているスペースとそのスペース内での作業(余分なものを切り捨てる)
  • 必要なスペースと必要なスペースの量を追跡し、必要に応じてさらにスペースを割り当てます(後でを空けてください) allあなたがもはやそれを必要としなくなったときに動的に割り当てられたスペース)。
関連する問題