gpt4 book ai didi

c - 打印到 stdout 并写入文件时 C 字符串中的垃圾值

转载 作者:行者123 更新时间:2023-12-02 21:44:31 29 4
gpt4 key购买 nike

我正在研究 C 字符串和流,以便更好地理解它们。我有这个测试程序来从输入文件读取固定大小的数据 block 到缓冲区,将缓冲区内容存储在中间存储中(在这种情况下,我希望存储能够存储三个不同的“读取”)并且然后将读取的字符串和中间存储中的字符串之一写入输出文件。

对此的说明:在每次迭代中,我只使用中间存储的前两个位置,并将第二个“存储的字符串”写入文件。

代码:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 3
#define BUFFER_SIZE 5

int main(int argc, char** argv) {
FILE* local_stream_test = fopen("LOCAL_INPUT_FILE","r");
FILE* local_output_test = fopen("LOCAL_OUTPUT_TEST","w");

if(!local_stream_test) {
puts("!INPUT FILE");
return EXIT_FAILURE;
}
if(!local_output_test) {
puts("!OUTPUT FILE");
return EXIT_FAILURE;
}
char my_buffer[BUFFER_SIZE];
char test[SIZE];
char* test2[SIZE];
memset(my_buffer,0,sizeof(my_buffer));
memset(test,0,sizeof(test));
memset(test2,0,sizeof(test2));

int read = fread( my_buffer, sizeof(my_buffer[0]), sizeof(my_buffer)/sizeof(my_buffer[0]), local_stream_test );

printf("FIRST READ TEST: %d\n",read);
printf("\tMY_BUFFER, SIZEOF: %lu, STRLEN: %lu\n",sizeof(my_buffer),strlen(my_buffer));

fwrite(my_buffer,sizeof(my_buffer[0]),/*strlen(aux)*/ read,local_output_test);
char* aux_test = strdup(my_buffer);
printf("\tAUX_TEST STRLEN: %lu, ## %s\n",strlen(aux_test), aux_test);
free(aux_test);
aux_test = NULL;

while(read > 0) {
if(feof(local_stream)) {
puts("BYE");
break;
}
read = fread( my_buffer, sizeof(my_buffer[0]), sizeof(my_buffer)/sizeof(my_buffer[0]), local_stream_test );
aux_test = strdup(my_buffer);

if(!aux_test) {
puts("!AUX_TEST");
break;
}


printf("READ TEST: %d\n",read);
printf("\tMY_BUFFER, SIZEOF: %lu, STRLEN: %lu\n",sizeof(my_buffer),strlen(my_buffer));
printf("\tAUX_TEST, SIZEOF: %lu, STRLEN: %lu ** SIZEOF *AUX_TEST: %lu, SIZEOF AUX_TEST[0]: %lu\n",sizeof(aux_test),strlen(aux_test),sizeof(*aux_test),sizeof(aux_test[0]));

fwrite(aux_test,sizeof(aux[0]),/*strlen(aux)*/ read,local_output_test);

printf("** AUX_TEST: %s\n",aux_test);
test2[0] = aux_test;
test2[1] = aux_test;
test2[1][3] = toupper(test2[1][3]);

fwrite(test2[1],sizeof(test2[1][0]),read,local_output_test);

printf("\n** TEST2[0] SIZEOF: %lu, STRLEN: %lu, TEST2[0]: %s\n",sizeof(test2[0]),strlen(test2[0]),test2[0]);
printf("\n** TEST2[1] SIZEOF: %lu, STRLEN: %lu, TEST2[1]: %s\n",sizeof(test2[1]),strlen(test2[1]),test2[1]);

strcpy(test2[1],aux_test);
printf("** COPIED TEST2[1]: %s\n",test2[1]);
free(aux_test);
aux_test = NULL;
puts("*******************************************");
}
return EXIT_SUCCESS;
}

输入文件:

converts a byte string to a floating point value
converts a byte string to an integer value
converts a byte string to an integer value

当打印字符串时,我在第二次读取后在其末尾得到了额外的垃圾值。以下是从文件中第一次、第二次和第三次读取的 stdout 中的输出:

FIRST READ TEST: 5
MY_BUFFER, SIZEOF: 5, STRLEN: 5
AUX_TEST STRLEN: 5, ## conve
READ TEST: 5
MY_BUFFER, SIZEOF: 5, STRLEN: 5
AUX_TEST, SIZEOF: 4, STRLEN: 5 ** SIZEOF *AUX_TEST: 1, SIZEOF AUX_TEST[0]: 1

** AUX_TEST: rts a

** TEST2[0] SIZEOF: 4, STRLEN: 5, TEST2[0]: rts a

** TEST2[1] SIZEOF: 4, STRLEN: 5, TEST2[1]: rts a
** COPIED TEST2[1]: rts a

*******************************************
READ TEST: 5
MY_BUFFER, SIZEOF: 5, STRLEN: 13
AUX_TEST, SIZEOF: 4, STRLEN: 13 ** SIZEOF *AUX_TEST: 1, SIZEOF AUX_TEST[0]: 1

** AUX_TEST: byte▒▒▒▒

** TEST2[0] SIZEOF: 4, STRLEN: 13, TEST2[0]: byTe▒▒▒▒


** TEST2[1] SIZEOF: 4, STRLEN: 13, TEST2[1]: byTe▒▒▒▒

** COPIED TEST2[1]: byTe▒▒▒▒

令我困扰的是,当垃圾值开始出现时,字符串的长度大于从文件中读取的字节:135 。我已经尝试过使用 BUFFER_SIZE,但在打印到 stdout 时我总是会得到垃圾值,除非大小足以一次性读取文件。

例如,BUFFER_SIZE 等于 500,这是 stdout 中的输出:

FIRST READ TEST: 135
MY_BUFFER, SIZEOF: 300, STRLEN: 135
AUX_TEST STRLEN: 135, ## converts a byte string to a floating point value
converts a byte string to an integer value
converts a byte string to an integer value

BYE

生成的输出文件:

BUFFER_SIZE = 5

converts arts a byte byTe stri stRing tong To a fl a FloatinoatIng poig pOint vant Value
clue
converonvErts a ts A byte bytE strinstrIng to g tO an inan IntegertegEr valu vaLue
cone
cOnvertsverTs a by a Byte stte String rinG to anto An inte inTeger vger value
aluE

BUFFER_SIZE = 500:与输入文件相同。

所以,我正在访问越界内存,对吧?但是哪里?我找不到这个问题的根源(很可能我对如何使用 C 字符串有误解)。

PS:

我读到here也许我的问题是我忘记在字符串末尾添加 NULL 标记。正在做:

 test2[0] = aux_test;
test2[0][ strlen(aux_test)+1 ] = '\0';

/* OR THIS */
test2[0][read+1] = '\0';

产生相同的结果。

最佳答案

您的部分问题是您正在读取数组范围之外的内容,并且 fread()当然不会 null 终止任何东西。

例如:

printf("\tMY_BUFFER, SIZEOF: %lu, STRLEN: %lu\n",sizeof(my_buffer),strlen(my_buffer));

您将 5 个字节的数据读入一个大小为 5 个字节的数组中。 strlen()报告5;您很幸运,数组末尾之外的第一个字节恰好是零字节,但由于它位于数组之外,因此您在此时调用了未定义的行为(即使您得到了预期的答案)。

在循环中,在第一次迭代中,toupper()大小写转换空白,这不会改变它。 test2[0]test2[1]两者都指向同一个字符串,因此如果 toupper()做了任何事情,都会影响这两个指针指向的值。

当垃圾值“出现”时,您已在 my_buffer 末尾之后将非零字节放入数据中。 ,以及 strlen()读取这些非零字节,直到达到零字节。所以,问题都是由于不能确保您的字符缓冲区在分配的长度内以空终止。当您调用未定义的行为时,可能会发生奇怪的事情。

请注意,如果您使用 printf("<<%.*s>>\n", read, my_buffer);您将只打印已读取的数据字节。


您询问的是:

test2[0] = aux_test;
test2[0][ strlen(aux_test)+1 ] = '\0';
/* OR THIS */
test2[0][read+1] = '\0';

您正在访问超出所提供内容末尾的一个字节。根据定义,strlen(str)返回第一个数字len这样str[len] == '\0' 。当你写test2[0][[strlen(aux_test)+1] = '\0';时因此,您将在字符串中第一个空值的末尾之外写入一个字节。 test2[0][read+1] = '\0';赋值,假设您刚刚读取了 5 个字节,则会覆盖 test2[0][6] ,但读取的数据的最后一个字节位于 test2[0][4] 中,所以你没有改变 test2[0][5] (目前尚不清楚您是否可以这样做)。

test2[0][strlen(aux_test)] = '\0';  // No-op, but safe
test2[0][read] = '\0'; // If you left enough space, null terminates the input

关于c - 打印到 stdout 并写入文件时 C 字符串中的垃圾值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19770920/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com