读/ proc程序

时间:2017-02-24 12:34:08

标签: c

我正在尝试编写一个具有获取进程详细信息的函数的脚本。

到目前为止我已经

#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;
}

我仍然发现指针和记忆有点模糊。当我在没有

的情况下运行此脚本时
n = getField(statusf, "Name:", 5);

我得到正确的输出(例如S - 睡觉);

但是当我调用函数来获取进程名称时,我似乎也得到了同样的结果,例如。

状态:ntary_ctx 名称:ntary_ctx

这甚至都不是正确的名字。我认为问题必须是函数变量保持价值。但我认为当一个函数返回其内存然后弹出堆栈。

3 个答案:

答案 0 :(得分:4)

代码重新调整指向局部变量的指针 这是无效的 - 它是未定义的行为(UB)。 @stark
这解释了&#34;我似乎得到了两个&#34;同样的输出,因为一个可能的UB是重复使用相同的缓冲区。另一种可能性是代码崩溃,以及其他候选者。

// Bad code
char* getField(FILE* file, char* prop, int len){
 char line[100], *p;
 ...
 p = line + len + 1;
 ...
 return p;  // `p` points to `line[]`
}

代码需要复制。可以通过分配或传入目的地来完成此操作,如下所示。

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();
...

更好的代码会传递dest的大小,因此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();
...

答案 1 :(得分:1)

一个问题是,在WHERE中,您正在返回getField(),这是指向p的指针加上一些偏移量。但是line是该函数中的局部变量,因此当函数终止时它超出了范围。 The answer是一个很好的解释。

作为第一步,你可以让它line在函数返回后被允许使用指针,但是第二个调用仍会覆盖你通过第一次调用读取的内容。 因此,最好的方法是为值传递一个额外的缓冲区:

static char line[100]

并且在main()中你将有两个不同的缓冲区

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;
}

答案 2 :(得分:0)

如果您使用该方法,则需要在每次读取字段时关闭并重新打开文件,或者在leat倒带到开头时重新打开文件。它不是编写C输入文件解析器的好方法,但它可用于短文件和快速程序。