[英]Why is my variable corrupt after returning from a function?
下面是我的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 //用於1
mypassword //用於2
myname // 3
mypasswo //為4
我不明白為什么會這樣。 有誰對這有什么想法?
您的問題是您要為lines
數組的各個部分分配用戶名和密碼。 lines
數組是一個局部變量,在set_credentials
完成后,分配給它的內存不再安全。 要解決此問題,請使用malloc
獲取您的用戶名和密碼的內存,或者使lines
成為username
和password
為的全局變量。
您已經創建了兩個指針username
和password
,它們指向在特定函數堆棧框架上創建的函數局部變量。 當函數返回時,這些指針將指向垃圾,因為堆棧幀已被破壞,因此函數的局部變量也是如此。
您需要將變量作為args傳遞給set_credentials
函數,或者需要創建一個struct
,該struct
可以從正確填充的函數中返回。 按值返回結構。 無需指針。
大衛確定了您的問題。 一種解決方案是分配該函數可以填充的兩個字符數組。
#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++;
}
}
您可以在函數中使用靜態變量,該函數允許您返回指向它的指針,因為即使在函數退出后,靜態變量也會存在。
#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++;
}
}
這是使用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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.