2016-04-26 4 views
-1

私は何が間違っているのかよくわかりません。 idを作成するためにpidhostnameを連結しようとしています。文字列とintを連結すると、Cのセグメント化エラーが発生する

char *generate_id(void) { 
    int ret; 
    char id[1048]; 
    char hostname[1024]; 
    pid_t pid = getpid(); 
    //hostname[1023] = '\0'; 

    if ((ret = gethostname(hostname,1024) < 0)) { 
     perror("gethostname"); 
     exit(EXIT_FAILURE); 
    } 
    sprintf(id, "%s%d", pid); 
    printf("hostname is %s\n", hostname); 
    printf("The process id is %d\n", pid); 
    printf("The unique id is %s", id); 

    return id; 
} 

編集:いくつかの答えを読んだ後に

更新コード:

char *generate_id(void) { 
    int ret; 
    char hostname[1024]; 
    pid_t pid = getpid(); 
    //hostname[1023] = '\0'; 

    if ((ret = gethostname(hostname,1024) < 0)) { 
     perror("gethostname"); 
     exit(EXIT_FAILURE); 
    } 

    int size = snprintf(NULL, 0, "%s%d", hostname, pid); 
    char * id = malloc(size + 1); 

    printf("hostname is %s\n", hostname); 
    printf("The process id is %d\n", pid); 
    printf("The unique id is %s\n", id); 

    return id; 
} 

EDIT:

の作業コード:

char *generate_id(void) { 
    int ret; 
    char hostname[1024]; 
    pid_t pid = getpid(); 
    //hostname[1023] = '\0'; 

    if ((ret = gethostname(hostname,1024) < 0)) { 
     perror("gethostname"); 
     exit(EXIT_FAILURE); 
    } 

    int size = snprintf(NULL, 0, "%s%d", hostname, pid); 
    char * id = malloc(size + 1); 
    sprintf(id, "%s%d", hostname, pid); 
    printf("hostname is %s\n", hostname); 
    printf("The process id is %d\n", pid); 
    printf("The unique id is %s\n", id); 

    return id; 
} 
+1

sprintf '%s%d'そして' pid'だけを提供しますか? 2つの書式設定文字があるので、2つの値を指定する必要があります –

+0

なぜsprintfの '%s%d'を'%d 'にするべきですか – JackVanier

+1

'pid_t pid'を' int'引数。 'sprintf(id、"%d "、(int)pid);' –

答えて

3

問題:

sprintf(id, "%s%d", pid); 

あなたのフォーマット文字列は、2つのフォーマッタ(文字列の%sintため%d)を持って、まだあなただけのpid_tを渡します。あなたはおそらく意味:%s

sprintf(id, "%s%d", hostname, pid); 

か、あなたのコードで

sprintf(id, "%d", pid); 

は、ポインタとして pidを解釈します。文字列のフォーマットを逆参照しようとすると、無効なポインタ値であるため、セグメント化エラーが発生します。

あなたのメモリ管理と問題:

しかし、その後未定義の動作はあなたのコードでもあります:あなたは、スタック割り当ての配列であることをidを宣言していますが、ここでポインタに崩壊その配列を(返却しています)。これも間違っており、後でクラッシュする可能性があります。

あなたは、このようなヒープ割り当ての配列にidを変更する必要があります。

char * id = malloc(1024); 

あなたgenerate_id関数の呼び出し側はそれを行うの時にメモリをfreeする必要があります。

必要な領域だけを割り当てることをお勧めします。あなたはセグメンテーションフォルトしているが、あなたはいくつかの問題を持っているところ

// Determine how much space the string needs. 
int size = snprintf(NULL, 0, "%d", pid); 
// Allocate the required space plus NULL termination. 
char * id = malloc(size + 1); 
// Actually print the string. 
sprintf(id, "%d", pid); 
+0

助けてくれてありがとう、私はユニークなIDを印刷しようとすると、質問のコードを更新しました。 –

+0

これは、あなたがスペースを_allocate_するだけだからですが、実際に 'sprintf'を呼んでいないからです。まず、特別な方法(最初の2つの引数として 'NULL'と' 0')で 'snprintf'が呼び出されます(名前に余分な' n 'があ​​ることに注意してください)。この方法でサイズを測定します。次に、 'malloc'でスペースを割り当て、' sprintf'でそのスペースに実際に印刷する必要があります。 – DarkDust

0
sprintf(id, "%s%d", pid); 

%sと%dの2つのセレクタがありますが、パラメータ(pid)は1つのみです。整数の代わりに文字列と整数を入れる必要があります。あなたのフォーマット文字列と

1

わからない:あなたはこのようにそのためのsnprintfを使用することができます。

snprintf()ははるかに安全で、id []バッファをオーバーランさせません。 sprintfがバッファをオーバーランさせる可能性があります。

上記のようにsprintf(id、 "%s%d"、pid)が悪いです。

戻り値は、スタック上の値へのポインタを返すため、不良です。あなたが戻ってすぐに、スタックはもはやあなたのものではありません。

+0

どのように文字列を正しく返すのですか? –

+0

メモリ(malloc)を割り当てて呼び出し元に解放するか、呼び出し元がそのルーチンを再度呼び出す前にコピーまたは使用する必要があることを知っている静的バッファを使用するか、または同様の方法を使用する必要があります。 – Russ

関連する問題