以下是我的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
我无法理解为什么会这样做。有没有人想到为什么会这样?
答案 0 :(得分:2)
您的问题是您要为lines
数组的部分分配用户名和密码。 lines
数组是一个局部变量,set_credentials
完成后分配给它的内存不再安全。要解决此问题,请使用malloc
获取用户名和密码的内存,或者使lines
成为username
和password
等全局变量。
答案 1 :(得分:1)
您已经创建了两个指针username
和password
,它们指向在该特定功能堆栈框架上创建的函数局部变量。当函数返回时,这些指针将指向垃圾,因为堆栈帧已被破坏,因此函数局部变量。
您需要将变量作为参数传递给set_credentials
函数,或者您需要创建一个struct
,您可以从正确填充的函数中返回该变量。按值返回结构。不需要指针。
答案 2 :(得分: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++;
}
}
答案 3 :(得分: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++;
}
}
答案 4 :(得分: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);
}
}