2017-02-24 5 views
3

私は、プロセスの詳細を取得する関数を持つスクリプトを作成しようとしています。Read/procプログラム

これまでのところ、私はまだ少しファジーポインタとメモリを見つけています

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

char* getField(FILE* file, char* prop, int len){ 
char line[100], *p; 

while(fgets(line, 100, file)) { 
    if(strncmp(line, prop, len) != 0) 
      continue; 

    p = line + len + 1; 
    while(isspace(*p)) ++p; 

    break; 
} 

return p; 
} 

int main(int argc, char *argv[]) { 

    char tgid[40], status[40], *s, *n; 
    FILE* statusf; 

    printf("Please Enter PID\n"); 

    if (fgets(tgid, sizeof tgid, stdin)) { 
    //Remove new line 
    strtok(tgid, "\n"); 
    snprintf(status, 40, "/proc/%s/status", tgid); 

    statusf = fopen(status, "r"); 
    if(!statusf){ 
     perror("Error"); 
     return 0; 
    } 

    s = getField(statusf, "State:", 6); 
    n = getField(statusf, "Name:", 5); 

    printf("State: %s\n", s); 
    printf("Name: %s\n", n); 

    }else{ 
    printf("Error on input"); 
    } 

    fclose(statusf); 
    return 1; 
} 

を持っています。このスクリプトを実行しないで

私は正しい出力を得ます(例:S - Sleeping)。

しかし、私がプロセス名を取得するために関数を呼び出すとき、私は両方のために同じものを入れているようです。

州:ntary_ctx 名:ntary_ctx

そして、それにも右の名前ではありません。私は問題は、変数がそこに保持している関数でなければならないと思う。しかし、私は、関数が返ってくると、そのメモリがスタックから飛び出すことを考えました。

+7

は、Cプログラムは感謝@rturスクリプト – rtur

+2

ではないことを処理することができdestの大きさで通過するだけのタイトルを変更。私は学ぶべきことがたくさんあります –

+0

すべての警告とデバッグ情報( 'gcc -Wall -g')でコンパイルし、デバッガ(' gdb')を使います。 BTW、Cについてもっと読む(例:[here](http://en.cppreference。com/w/c)) 'int 'pidを読み込むために' scanf'を使うことを検討してください。 –

答えて

4

コードは、ローカル変数へのポインタを再同調された二つの異なるバッファを持っています。
有効ではありません - 未定義の動作(UB)です。 @stark
これは、同じバッファが再利用されるということで、「私は両方に同じものが得られるようです」と説明しています。別の可能性は、他の候補の中でコードがクラッシュすることです。

コードはコピーを作成する必要があります。以下のように、割り当てや目的地を通過することでこれを行うことができます。

char* getField(FILE* file, char *dest, const char* prop, int len){ 
    if (problem) return NULL; 
    ... 
    return strcpy(dest, p); 
} 

// Example call 
char prop_state[100]; 
if (getField(statusf, prop_state, "State:", 6)) Success(); 
else Handle_Problem(); 
... 
char prop_name[100]; 
if (getField(statusf, prop_name, "Name:", 6)) Success(); 
... 

良いコードがそうgetField()ちょうどセマンティクスのために

char* getField(FILE* file, char *dest, size_t size, const char* prop, int len){ 
    ... 
    if (strlen(p) >= size) return NULL; // Not enough room 
    return strcpy(dest, p); 
} 

// usage 
if (getField(statusf, prop_state, sizeof prop_state, "State:", 6)) Success(); 
... 
+0

@davidKirwan注意:プロンプトを 'getField()'に渡して、必要に応じて再度プロンプトを表示するようにしてください。 'continue'はユーザーにフィードバックを提供しません。 [例](http://stackoverflow.com/a/41146306/2410359) – chux

+0

あなたの助けを借りてありがとう –

0

この方法を使用する場合は、フィールドの各読み込み時にファイルを閉じてから再度開くか、先頭から巻き戻しする必要があります。それは本当にCの入力ファイルのパーサーを書くための良い方法ではありませんが、短いファイルと簡単なプログラムのために行います。

+0

ああ大丈夫です。そうです、これはおそらくすべての種類の間違いです、私は適切なCプログラミングの実践について多くの研究をするつもりです。 –

+0

一般に、すべてのオプションを含む構造体を宣言し、configファイルからそれを埋め込む関数を記述します。したがって、設定ファイルは一度だけ読み込まれます。 –

1

getField()には、にオフセットを加えたpが返されています。しかし、lineはその関数内のローカル変数であるため、関数が終了するとスコープ外です。 The answerは大きな説明です。

最初のステップでは、関数が返った後にstatic char line[100]にポインタを使用できるようにすることができますが、2番目の呼び出しはまだ1番目の呼び出しで読み込んだものを上書きします。 ので、最善の方法は、値のための追加のバッファを渡すことです:

char* getField(FILE* file, char* prop, int len, char *value){ 
    char line[100], *p; // now it's ok 
    ... // everything at it is now before return 
    strcpy(value, p); 
    return value; 
} 

とメインで()あなたは

char name[100], state[100]; // at least same size as line - length of label 
.... 
s = getField(statusf, "State:", 6, state); 
n = getField(statusf, "Name:", 5, name); 
+0

彼は関数を複数回呼び出すため、静的は役に立ちません。 – stark

+0

@starkおっと、そうです、それを見ていません。私は答えを訂正します –

+0

複数の 'getField()'を表示する素晴らしい答えです。 – chux

関連する問題