gpt4 book ai didi

c - strncat 看起来像是在跨调用时保存数据?

转载 作者:太空宇宙 更新时间:2023-11-04 05:42:19 24 4
gpt4 key购买 nike

我发现 string.h 标准库中的 strncat 函数有一些奇怪的行为,希望得到一些帮助以了解发生了什么。


我的问题的症结在于我创建的一个名为 readLine 的函数,目的是将文件的行作为 char * 字符串返回,没有尾随的换行符终止符。该函数如下所示:

char * readLine(FILE * fp) {
char * chunk = NULL;
char * line = NULL;
int count = 0;

// iterate through chunks of a line until we reach the end (or an error)
while (fgets((chunk = malloc(sizeof(char) * BUFFER_SIZE)), BUFFER_SIZE, fp) != NULL) {

// realloc on a null pointer works like malloc
line = realloc(line, ++count * BUFFER_SIZE * sizeof(char));

printf("chunk's contents: %s\n", chunk);

// does chunk contain the end of a line?
if(strchr(chunk, '\n') == NULL) {
// concatenate string parts and continue loop
strncat(line, chunk, strlen(chunk) + 1);
free(chunk);

} else {
// we want to return a \0 terminated string without the \n
// expected position of \n in chunk is ({length of chunk}-1)
chunk[(strlen(chunk) - 1)] = '\0';

// concatenate string parts
strncat(line, chunk, strlen(chunk) + 1);
printf("readLine line: %s\n", line);
free(chunk);

break;
}
}
return line;
}

我在主循环中调用它,如下所示:

FILE * fp = NULL;

if ((fp = fopen(FILE_PATH, "r")) != NULL) {
char * line = NULL;

while ((line = readLine(fp)) != NULL) {
printf("main line: %s\n\n", line);
free(line);
}

fclose(fp);
}

现在奇怪的行为出现在我对 #define BUFFER_SIZE 1000 的定义中。这样设置后,我得到以下输出(这不是我想要的):

chunk's contents: I am on line 1
readLine line: I am on line 1
main line: I am on line 1

chunk's contents: Over here I am on line 2
readLine line: I am on line 1Over here I am on line 2
main line: I am on line 1Over here I am on line 2

chunk's contents: Line 3 here
readLine line: I am on line 1Over here I am on line 2Line 3 here
main line: I am on line 1Over here I am on line 2Line 3 here

chunk's contents: Look out for 4
readLine line: I am on line 1Over here I am on line 2Line 3 hereLook out for 4
main line: I am on line 1Over here I am on line 2Line 3 hereLook out for 4

chunk's contents: Johnny 5 alive!
readLine line: I am on line 1Over here I am on line 2Line 3 hereLook out for 4Johnny 5 alive!
main line: I am on line 1Over here I am on line 2Line 3 hereLook out for 4Johnny 5 alive!

但是 如果我将该定义更改为类似#define BUFFER_SIZE 20 的内容,我会得到我正在寻找的输出:

chunk's contents: I am on line 1

readLine line: I am on line 1
main line: I am on line 1

chunk's contents: Over here I am on l
chunk's contents: ine 2

readLine line: Over here I am on line 2
main line: Over here I am on line 2

chunk's contents: Line 3 here

readLine line: Line 3 here
main line: Line 3 here

chunk's contents: Look out for 4

readLine line: Look out for 4
main line: Look out for 4

chunk's contents: Johnny 5 alive!

readLine line: Johnny 5 alive!
main line: Johnny 5 alive!

我想我已将问题缩小到 strncat(line, chunk, strlen(chunk) + 1); 行。我不明白为什么在我的 BUFFER_SIZE 足够高时包含前面的 line

最佳答案

line = realloc(line, ++count * BUFFER_SIZE * sizeof(char));

不初始化分配的内存。因此,如果 readLine 中的第一个 realloc 将您在上一次调用中获得的内存块还给您 - 并非不可能,您的旧内容可能仍然存在。

无论如何,对于未初始化的内存,第一个 strncat 可能会调用未定义的行为,因为分配的内存中不需要 0 字节。

在进入循环之前给line分配一个缓冲区,并在第一个字节写入一个0

另外,不要使用

line = realloc(line, ++count * BUFFER_SIZE * sizeof(char));

如果 realloc 失败,您就会泄漏内存。你应该检查realloc的返回值,

char *temp = realloc(line, ++count * BUFFER_SIZE * sizeof(char));
if (temp == NULL) {
// Oops
} else {
line = temp;
}

并且不要在 fgets 调用中将 mallocchunk

while (fgets((chunk = malloc(sizeof(char) * BUFFER_SIZE)), BUFFER_SIZE, fp) != NULL)

如果 malloc 失败,那也会调用未定义的行为。 malloc 并在调用 fgets 之前进行检查,

while ((chunk = malloc(sizeof(char) * BUFFER_SIZE)) && fgets(chunk, BUFFER_SIZE, fp) != NULL)

关于c - strncat 看起来像是在跨调用时保存数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15166252/

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