17

ここで私が間違っていることを誰か教えてもらえますか? プログラムが segfault を起こすのはなぜですか? string1と の間に3 番目の文字列を挿入しようとしていstring2ます。

#include <stdio.h>

int main (void) 
{
char *string1 = "HELLO";
char *string2 = "WORLD";
char *stringX  = "++++";
char *string3;
printf ("%s,%s\n",string1,string2);
sprintf(string3,"%s%s%s",string1,stringX,string2);
printf ("NewVar: %s",string3);
}

sprintfが指すメモリアドレスに結果の値を保存しないのはなぜstring3ですか? 通常の配列として宣言すると機能しますが、配列string3へのポインターの場合は機能しませんchar

私はstring3メモリの場所を指していないと思っていましたが、私がそうするときはそうですprintf("%p",string3);

出力:

# ./concat
HELLO,WORLD,0x40042
4

5 に答える 5

36

ブリーフケースに入れたい現金の山があると想像してください。あなたは何が必要ですか?使用するブリーフケースの大きさを知るには、現金のサイズを測定する必要があります。また、現金を便利に持ち運ぶためのハンドルが必要です。

現金はあなたのひもです。ブリーフケースはメモリ空間です。ブリーフケースのハンドルはポインターです。

  1. 現金を測る: strlen(string1) + strlen(string2) + strlen(stringX). これを「合計」と呼びます。
  2. 十分な大きさのブリーフケースを用意してください。malloc(total+1)
  3. そしてそれにハンドルを置きます:string3

それをすべてまとめて...

char *string3 = malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);
sprintf(string3, "%s%s%s", string1, stringX, string2);

では、最初の試みの何が問題だったのでしょうか。あなたはブリーフケースを持っていませんでした。あなたは現金を持っていて、持ち手は持っていますが、真ん中にブリーフケースはありません。コンパイラーが現金を保持するための汚れたゴミ箱を提供したため、ランダムな方法で機能しているように見えました。ごみ箱にはスペースがある場合もあれば、ない場合もあります。そうでない場合、それを「セグメンテーション違反」と呼びます。

データがあるときはいつでも、そのデータにスペースを割り当てる必要があります。コンパイラは、 などの定数文字列にスペースを割り当てます"HELLO"。ただし、実行時に作成される文字列にはスペースを割り当てる必要があります。

于 2013-11-04T16:51:05.320 に答える
10

sprintfそこに値を格納します。問題は、ポインター string3 の値が初期化されていないため、ランダムなメモリを上書きしているだけです。

あなたが持っている1つのオプションは、静的文字列バッファを使用することです:

char string3[20];
snprintf(string3, sizeof(string3), "Hello!");

または、asprintfGNU libc ベースのシステムで使用して、適切なスペースを自動的に割り当てることができます。

char * string3;
asprintf(&string3, "Hello!");
// ... after use
free(string3); // free the allocated memory
于 2013-11-04T16:49:30.623 に答える
8

sprintf書き込む文字列にメモリを割り当てません。書き込むには有効な文字列を指定する必要がありますが、現在は初期化されていないポインターを渡しています。

最も簡単な修正は変更することです

char *string3;
sprintf(string3,"%s%s%s",string1,stringX,string2);

char string3[200];
sprintf(string3,"%s%s%s",string1,stringX,string2);

この場合、snprintf代わりに使用してバッファオーバーフローを防ぐことができます

char string3[200];
snprintf(string3,sizeof(string3),"%s%s%s",string1,stringX,string2);

または、実行時に のサイズを決定し、終了時にこのメモリにstring3注意することで、より長いソース文字列に対処することもできます。free

char* string3 = malloc(strlen(string1) + strlen(stringX) + strlen(string2) + 1);
if (string3 == NULL) {
    // handle out of memory
}
sprintf(string3,"%s%s%s",string1,stringX,string2);
...
free(string3);
于 2013-11-04T16:48:08.007 に答える
4

ヒープ上に配置する必要がある場合はスペースを割り当てるstring3か、mallocそうでない場合は文字配列として宣言する必要があります。

于 2013-11-04T16:47:16.700 に答える