[英]Why is my variable corrupt after returning from a function?
Below is my c code: 下面是我的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++;
}
}
Now, when I run the code, I get this: 现在,当我运行代码时,我得到了:
myname //for 1 myname //用于1
mypassword //for 2 mypassword //用于2
myname // for 3 myname // 3
mypasswo // for 4 mypasswo //为4
I can't understand why that behavior. 我不明白为什么会这样。 Have anyone ideea about why that? 有谁对这有什么想法?
Your problem is that you are assigning username and password to parts of the lines
array. 您的问题是您要为lines
数组的各个部分分配用户名和密码。 The lines
array is a local variable and the memory allocated to it is no longer safe after set_credentials
finishes. lines
数组是一个局部变量,在set_credentials
完成后,分配给它的内存不再安全。 To fix it, use malloc
to get the memory for your username and password, or make lines
a global variable like username
and password
are. 要解决此问题,请使用malloc
获取您的用户名和密码的内存,或者使lines
成为username
和password
为的全局变量。
You have created two pointers username
and password
which point to function local variables created on that particulars functions stack frame. 您已经创建了两个指针username
和password
,它们指向在特定函数堆栈框架上创建的函数局部变量。 When the function returns, these pointers will point to garbage, since the stack frame has been destroyed and so the function local variables. 当函数返回时,这些指针将指向垃圾,因为堆栈帧已被破坏,因此函数的局部变量也是如此。
You need to pass the variables as args to your set_credentials
function or you need create a struct
which you can return from your function filled up properly. 您需要将变量作为args传递给set_credentials
函数,或者需要创建一个struct
,该struct
可以从正确填充的函数中返回。 Return the struct by value. 按值返回结构。 No need for pointers. 无需指针。
David identifies your problem. 大卫确定了您的问题。 One solution is to allocate two character arrays that the function can populate. 一种解决方案是分配该函数可以填充的两个字符数组。
#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++;
}
}
You can use a static variable in the function which allows you to return a pointer to it, since a static variable will be around even after the function has exited. 您可以在函数中使用静态变量,该函数允许您返回指向它的指针,因为即使在函数退出后,静态变量也会存在。
#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++;
}
}
Here is a version that uses malloc() and free(). 这是使用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.