分配给标准输出的文件指针的值无故递增

问题描述 投票:0回答:1

我正在尝试使用 stdout 文件指针通过 fputc 输出我的数据。代码看起来像这样:

...
int c;
FILE *in, *out;

...
in = fopen(*argv++, "r");
if (!in) {
    printf("failed to open file %s\n", *(argv - 1));
    return 1;
}
out = (o) ? fopen(*argv++, "w") : stdout;   [1]
if (!out) {
    printf("failed to open file %s\n", *(argv - 1));
    return 1;
}

...
while ((c = fgetc(in)) != EOF) {        [2]
    ...
}
...

我不提供输出文件,因此,我的

out
文件指针指向
stdout
。 当我尝试使用
fputc
stdout
中输出数据时,如

fputc(c, out);     /* not inside the loop above, and 'c' has completely different value */

我遇到分段错误。赋值 (

out
) 和使用 (
out = stdout
) 之间没有提及
fputc(c, out)
。 尽管如此,我发现由于某种神奇的原因,在使用时(
fputc
),
out
指向而不是
stdout
, 但位于
<stdout + 6>
stdout
地址后 6 个字节)。我不知道为什么。这是我的调试器会话。

断点1:

(gdb) c
Continuing.

Breakpoint 3, main (argc=1, argv=0x7fffffffe200) at source.c:73
73          out = (o) ? fopen(*argv++, "w") : stdout;
(gdb) n

Hardware watchpoint 2: out

Old value = (FILE *) 0x0
New value = (FILE *) 0x7ffff7fa7780 <_IO_2_1_stdout_>
main (argc=1, argv=0x7fffffffe200) at source.c:74

断点2:

(gdb) c
Continuing.

Hardware watchpoint 2: out

Old value = (FILE *) 0x7ffff7fa7780 <_IO_2_1_stdout_>
New value = (FILE *) 0x7ffff7fa7781 <_IO_2_1_stdout_+1>
main (argc=1, argv=0x7fffffffe200) at source.c:80
80          while ((c = fgetc(in)) != EOF) {

发生了很多事情(至少对我来说)。但这里的关键点是

out
文件指针的值在没有任何明显原因的情况下增加。我需要一些帮助 语言律师(或懂得 C 的人)。这个神奇的功能是叫“UB”还是别的什么? 在这个循环中,我将
in
文件指针与
stdin
进行比较,使用我的动态字符串(听起来像麻烦)和一个整数数组。 无论如何,这与流无关(或者至少我希望如此)。

我期望文件指针指向同一位置而不改变其自身的值。这个问题可能没有提供太多信息,但我认为其他细节与文件指针或 i/o 流无关。

更新: 正如许多人在评论中指出的那样,没有足够的信息。抱歉。这是完整的代码。

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

#define MAX 'e'

typedef struct {
    char *s;
    char *t;
    char *u;
    int l;
} string;

void put_char(string *s, char c)
{
    if (!s->s) {
        s->s = malloc(s->l = 2);
        s->t = s->s;
        s->u = s->s;
    } else if (s->t - s->s >= s->l) {
        if ((s->s = realloc(s->s, s->l <<= 1)) == NULL) {
            printf("failed to reallocate string\n");
            return;
        }
        s->t = s->s + (s->l >> 1);
        s->u = s->s;
    }
    *s->t++ = c;
}

int get_char(string *s)
{
    if (*s->u)
        return *s->u++;
    else
        return 0;
}

int caesar(int c, int s)
{
    if (isalpha(c))
        return ((tolower(c) - 'a' + s) % 26 + 26) % 26 + 'a';
    else 
        return c;
}

int main(int argc, char const *argv[])
{
    int d[26];
    int c, f, i, m, o;
    FILE *in, *out;
    string s;

    i = o = 0;
    while (--argc > 0 && **++argv == '-')
        while (c = *++*argv)
            switch (c) {
                case 'i':
                    i = 1;
                    break;
                case 'o':
                    o = 1;
                    break;
                default:
                    printf("decrypt: illegal option %c\n", c);
                    break;
            }
    in = (i) ? fopen(*argv++, "r") : stdin;
    if (!in) {
        printf("failed to open file %s\n", *argv);
        return 1;
    }
    out = (o) ? fopen(*argv++, "w") : stdout;
    if (!out) {
        printf("failed to open file %s\n", *argv);
        return 1;
    }
    for (i = 0; i < 26; i++)
        *(d + i) = 0;
    while ((c = fgetc(in)) > 0) {
        if (in == stdin)
            put_char(&s, c);
        if (isalpha(c))
            (*(d + c - 'a'))++;
    }
    if (in == stdin)
        put_char(&s, '\0');
    for (i = m = 0; i < 26; i++)
        if (*(d + i) > *(d + m))
            m = i;
    f = -abs('a' + m - MAX);
    if (in == stdin) {
        while ((c = get_char(&s)) > 0)
            fputc(caesar(c, f), out);
    } else {
        fseek(in, 0, SEEK_SET);
        while ((c = fgetc(in)) > 0)
            fputc(caesar(c, f), out);
    }
    return 0;
}
c stdout file-pointer
1个回答
0
投票

您的所有

get_char(&s)
put_char(&s)
调用都会表现出 未定义的行为,因为您在进行这些调用之前尚未初始化
s
的任何成员。在评估
s->s
之前,
if (!s->s)
没有任何有意义的值(并且可能与
s->u
中的
if (*s->u)
相同),因此之后的一切都是可疑的。您需要初始化
string
成员。

© www.soinside.com 2019 - 2024. All rights reserved.