1

下面是我的c代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

char *username;
char *password;

void set_credentials(char*, char*);

int main(void)
{
  set_credentials();
  printf("%s\n", username);     //look here 3
  printf("%s\n", password);     //look here 4
  return EXIT_SUCCESS;
}

void set_credentials(char *username, char *password)
{
  char c;
  char lines[2][100];
  char * tmp = * lines;
  char * user = "user";
  int i = 0;
  FILE *fp = fopen("/netnfork/config/netnfork_credentials.properties", "r");

  if (fp == NULL)
    exit(EIO);
  while ((c = fgetc(fp)) != EOF)
  {
    if (c != '\n')
    {
      *tmp = c;
      tmp++;
    } else {
      *tmp = '\0';
      i++;
      tmp = lines[i];
    }
  }
  fclose(fp);
  i = 0;
  while (i < 2)
  {
    if (strncmp(user, lines[i], 4) == 0)
    {
      username = lines[i] + 5;
      printf("%s\n", username); //look here 1
    } else {
      password = lines[i] + 9;
      printf("%s\n", password);  //look here 2
    }
    i++;
  }
}

现在,当我运行代码时,我得到了这个:

myname //for 1
mypassword //for 2
myname //for 3
mypasswo��� //for 4

我不明白为什么会有这种行为。有人知道为什么吗?

4

5 回答 5

2

您的问题是您正在为lines数组的某些部分分配用户名和密码。该数组是一个局部变量,分配给它的内存在完成lines后不再安全。set_credentials要修复它,请使用malloc获取用户名和密码的内存,或创建lines一个全局变量,如usernameand passwordare。

于 2012-09-03T12:35:10.223 回答
1

这是一个使用 malloc() 和 free() 的版本。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>


/* "user " */
#define USERLINE_PREFIX 5
/* "password " */
#define PASSLINE_PREFIX 9



void set_credentials(char**, char**);

int main(void)
{
  /* to point to the username and password obtained from a text file */
  char *username = NULL;
  char *password = NULL;
  set_credentials(&username,&password);
  /* (original scheme) printf("username: %s\n", username);  */
  /* (original scheme) printf("password: %s\n", password);  */
  printf("username: %s\n", username + USERLINE_PREFIX ); // line starts "user "    
  printf("password: %s\n", password + PASSLINE_PREFIX ); // line starts "password "
  /* (original scheme)  free(username - USERLINE_PREFIX); */
  /* (original scheme) free(password - PASSLINE_PREFIX); */
  free(password);
  free(username);
  return EXIT_SUCCESS;
}

void set_credentials(char **username, char **password)
{
  /* file format:
  line 1 ->user <username>
  line 2 ->password <password>
  */
  char c;
  #define FILE_LINES 2
  #define MAX_LINE_LENGTH 100
  int i = 0, j = 0;
  char *lines[FILE_LINES];
  char *tmp = NULL;
  char *user = "user ";
  char *pass = "password ";
  char user_found = 0, password_found = 0;
  for (j = 0; j < FILE_LINES; j++)
  {
    lines[j] = malloc( MAX_LINE_LENGTH + 1 );
    lines[j][0] = '\0';
  }
  tmp = lines[0];
  const char *filename = "/netnfork/config/netnfork_credentials.properties";
  FILE *fp = fopen(filename, "r");

  if (fp == NULL)
  {
    printf("ERROR %d trying to open %s\n",errno,filename);
    /* if not exiting program, would need to free() here */
    exit(EIO);
  }
                                /* in case more lines than expected */
  while ((c = fgetc(fp)) != EOF && i < FILE_LINES)
  {
    if (c != '\n')
    {
      *tmp = c;
      tmp++;
    } else {
      *tmp = '\0';
      i++;
      tmp = lines[i];
    }
  }
  if ( i < 2 )  {
     printf("ERROR: file %s is incomplete needs %d lines (password and user)\n",filename,FILE_LINES);
     /* if not exiting program, would need to free() here */
     exit(1);
  }
  fclose(fp);
  i = 0;
  while (i < FILE_LINES)
  {
    if (strncmp(user, lines[i], USERLINE_PREFIX) == 0)
    {
       user_found = 1;
       /* (original scheme) *username = lines[i] + USERLINE_PREFIX; */
       *username = lines[i];
    }
    else if  ( strncmp (pass, lines[i],PASSLINE_PREFIX) == 0 ) {
       password_found = 1;
       /* (original scheme) *password = lines[i] + PASSLINE_PREFIX; */
       *password = lines[i];
    }
    else {
       printf("ERROR: invalid line in file:\n");
       printf("%s\n",lines[i]);
       /* if not exiting program, would need to free() here */
       exit(1);
    }
    i++;
  }
  /* check for the extremely unlikely event that the two lines are both of the same type */
  if ( ! (password_found && user_found ) )
  {
     printf("ERROR: file %s is invalid, missing %s line\n",filename, (user_found) ? "password" : "user" );  
     /* if not exiting program, would need to free() here */
     exit(1);
  }
}
于 2012-09-04T08:44:20.780 回答
1

大卫发现了你的问题。一种解决方案是分配函数可以填充的两个字符数组。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>



void set_credentials(char*, char*);

int main(void)
{
  /* to hold the username and password obtained from a text file */
  char username[200] = { '\0' };
  char password[200] = { '\0' };
  set_credentials(username,password);
  printf("%s\n", username);     //look here 3
  printf("%s\n", password);     //look here 4
  return EXIT_SUCCESS;
}

void set_credentials(char *username, char *password)
{
  char c;
  char lines[2][100];
  int i = 0;
  char *tmp = *lines;
  char *user = "user";
  char *pass = "password";


  const char *filename = "/netnfork/config/netnfork_credentials.properties";
  FILE *fp = fopen(filename, "r");

  if (fp == NULL)
    exit(EIO);
  else
    printf("successfully opened %s\n",filename);
                                /* in case more than 2 lines */
                                /* or increase array first dimension */ 
  while ((c = fgetc(fp)) != EOF && i < 2)
  {
    if (c != '\n')
    {
      *tmp = c;
      tmp++;
    } else {
      *tmp = '\0';
      i++;
      tmp = lines[i];
    }
  }

  fclose(fp);
  i = 0;
  while (i < 2)
  {
    if (strncmp(user, lines[i], 4) == 0)
    {
      strcpy(username,lines[i] + 5);
    }
    else if  ( strncmp (pass, lines[i],8) == 0 ) {
      strcpy(password,lines[i] + 9);
    }
    else {
      /* can't assume file is correct so fatal error if not */
      printf("ERROR: invalid line in file:\n");
      printf("%s\n",lines[i]);
      exit(1);
    }
    i++;
  }
}
于 2012-09-03T13:49:49.913 回答
1

您已经创建了两个指针usernamepassword它们指向在该特定函数堆栈框架上创建的函数局部变量。当函数返回时,这些指针将指向垃圾,因为堆栈帧已经被销毁,函数局部变量也是如此。

您需要将变量作为 args 传递给您的set_credentials 函数,或者您需要创建一个struct可以从您的函数返回的正确填充的变量。按值返回结构。不需要指针。

于 2012-09-03T12:34:55.933 回答
1

您可以在函数中使用静态变量,它允许您返回指向它的指针,因为即使在函数退出后静态变量也会存在。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>


/* 
  In order to modify a caller's char in a function it must be passed as pointer to char 
  In order to modify a caller's "char *" in a function it must be passed as pointer to "char *" 
*/ 
void set_credentials(char**, char**);

int main(void)
{
  /* to point to the username and password obtained from a text file */
  char *username = NULL;
  char *password = NULL;
  /* pass the addresses of the char *'s so their contents can be modified */
  set_credentials(&username,&password);
  printf("%s\n", username);     //look here 3
  printf("%s\n", password);     //look here 4
  return EXIT_SUCCESS;
}

void set_credentials(char **username, char **password)
{
  char c;
#define MAX_FILE_LINES 2
  static char lines[MAX_FILE_LINES][100];
  int i = 0;
  char *tmp = *lines;
  char *user = "user";
  char *pass = "password";


  const char *filename = "/netnfork/config/netnfork_credentials.properties";
  FILE *fp = fopen(filename, "r");

  if (fp == NULL)
  {
    printf("ERROR: unable to open %s\n",filename);
    exit(EIO);
  }
  else
    printf("successfully opened %s\n",filename);
                                /* in case more lines than expected */
  while ((c = fgetc(fp)) != EOF && i < MAX_FILE_LINES)
  {
    if (c != '\n')
    {
      *tmp = c;
      tmp++;
    } else {
      *tmp = '\0';
      i++;
      tmp = lines[i];
    }
  }

  fclose(fp);
  i = 0;
  while (i < 2)
  {
    if (strncmp(user, lines[i], 4) == 0)
    {
      /* assign to the char * back in the calling routine */
      *username = lines[i] + 5;
    }
    else if  ( strncmp (pass, lines[i],8) == 0 ) {
      /* assign to the char * back in the calling routine */
      *password = lines[i] + 9;
    }
    else {
      /* can't assume file is correct so fatal error if not */
      printf("ERROR: invalid line in file:\n");
      printf("%s\n",lines[i]);
      exit(1);
    }
    i++;
  }
}
于 2012-09-04T07:39:18.927 回答