我是C编程的新手,我对指针有一些问题,特别是将它们用作参数。我尝试做的是从一个txt文件中读取一个存储它在变量中的值。我的方法就是这样:
int read_from_file(char path[], char *string){
//Variables
char ch;
char content[32];
int i=0;
FILE *file = fopen(path, "r");
if (file != NULL)
{
while( ( ch = fgetc(file) ) != EOF ){
content[i]=ch;
i++;
}
printf("File:%s\n", content); //This contains the actual result!
string = content;
fclose(file);
return EXIT_SUCCESS;
}else{
return EXIT_FAILURE;
}
}
int
main(int argc, char **argv){
char *string_1 = (char*) malloc(32*sizeof(char));
char *string_2 = (char*) malloc(32*sizeof(char));
char file_path_1[] = "file_1.txt";
char file_path_2[] = "file_2.txt";
read_from_file(file_path_1, string_1);
read_from_file(file_path_2, string_2);
printf("String 1 :%s\n", string_1);
printf("String 2 :%s\n", string_2);
}
但结果如下:
File:This is string 1!
File:This is string 2!
Symmetric Key :
Hash Key :
如何对此方法进行编程以在预定义的变量或指针中接收或存储字符串?提前致谢!
答案 0 :(得分:1)
您将数据从content
复制到string
的方法是错误的。您只是将string
指针更改为content
的值,但字符串指向的数据保持不变。
最简单的方法是直接将数据存储到string
,然后完全删除临时变量content
。
如果您要将数据从content
复制到string
,请使用memcpy()
。
另请注意,有一个名为fread()
的函数,它可以而且应该用于一次读取多个字节。
另请注意,为避免内存问题,应始终将缓冲区的大小作为参数传递给函数,以避免在缓冲区末尾写入或读取。
您还应该确保您的字符串始终以空值终止,方法是在最后一个字符后存储'\0'
。
在C
编程时,内存管理应该是主要关注点之一。不知道你正在做什么,或者暂时不考虑它,可能并且将导致记忆问题,在最好的情况下,这将表现为分段错误,并且在最坏的情况下保持隐藏并且是利用针对您的应用程序的远程代码执行攻击。即使具有多年C
经验的程序员仍然会犯这样的错误。因此,强烈建议至少阅读一些有关内存在C
中如何工作的教程和文章,字符串如何工作以及主要注意事项。
我也建议您使用(gcc
/ clang
)-Wall -Wextra -pedantic
来激活所有编译器警告,不要忽略警告,并通过valgrind
之类的软件定期运行程序检查它是否仍然没有错误。
您的代码中的一些问题:
fgetc()
会返回int
。您正在将其重新解释为char
,这会导致数据丢失。也就是说,如果输入文件包含字节0xFF
,则会将其简单地解释为EOF
。content
之外写入。这会导致未定义的行为,但最有可能的是,其他局部变量(i
,file
,ch
)可能会被覆盖,因为content
位于堆栈上。这个错误很可能一开始就没有引起注意,但却有非常丑陋,几乎无法解决的副作用。如果文件远大于32字节,则写入将在堆栈外,并可能导致分段错误。根据{{1}}标准库实现的具体情况,攻击者可以使用此错误来操纵C
指针,这将导致下一次调用file
来操纵任意位置程序的内存,例如标准库函数指针。熟练的攻击者可以手工制作一个特定的文件,使您的程序执行任意代码。fgetc()
所在的内存具有除content
之外的其他值,例如因为之前已调用过其他函数,或者文件大小正好是32字节,则表示该字符串为从'\0'
开始未正确地以空值终止,并且content[0]
将继续读取内存,直到它最终找到'\ 0'。这也是未定义的行为,但最有可能导致打印奇怪的字符或段错误。我不认为这个bug可以用于任何有用的攻击,但我可能会出错。答案 1 :(得分:1)
这里的问题是你明显打算通过" char * string"返回你的字符串。论点。你认为这一行:
string = content;
...应该返回字符串,但你所做的只是覆盖"字符串"堆栈上的指针变量,指针的值为" content"。你真正想要做的是复制来自"内容"的位置的数据。指向" string"的位置指向。
要做到这一点,你应该使用memcpy(),因为你已经分配了" string"指向。
答案 2 :(得分:0)
在你的函数read_from_file()中,缓冲区内容是一个局部变量。当你执行赋值时,string = content,变量,string获取内容的地址......它位于调用堆栈中。当函数返回时,该地址可能是垃圾或无效。
而不是做string = content,你需要像这样调用memcpy()......
memcpy(string, content, sizeof content)