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//
3for3mypasswo����//4for 4

なぜその振る舞いなのか理解できません。なぜそれについて誰かが考えていますか?

4

5 に答える 5

2

問題は、linesアレイの一部にユーザー名とパスワードを割り当てていることです。配列はローカル変数であり、lines配列に割り当てられたメモリは終了後に安全ではなくなりますset_credentials。これを修正するには、を使用mallocしてユーザー名とパスワードのメモリを取得するか、linesandareのようなグローバル変数を作成usernamepasswordます。

于 2012-09-03T12:35:10.223 に答える
1

2つのポインターusernamepassword作成し、その特定の関数スタックフレームで作成された関数ローカル変数を指します。関数が戻ると、スタックフレームが破棄され、関数のローカル変数が破棄されているため、これらのポインターはガベージを指します。

変数をargsとして関数に渡すか、関数から適切に入力して返すことができるをset_credentials 作成する必要があります。struct構造体を値で返します。ポインタは必要ありません。

于 2012-09-03T12:34:55.933 に答える
1

デビッドはあなたの問題を特定します。1つの解決策は、関数が設定できる2つの文字配列を割り当てることです。

#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

関数で静的変数を使用すると、関数へのポインターを返すことができます。これは、関数が終了した後でも静的変数が存在するためです。

#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 に答える
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 に答える