【问题标题】:Why don't regexec(), regcomp(), followed by print statements execute immediately?为什么 regexec()、regcomp() 和 print 语句不立即执行?
【发布时间】:2022-01-25 01:03:17
【问题描述】:

我有一个用 C 编码的功能正常的 HTTP 服务器。在向它添加正则表达式功能的过程中,我遇到了我的程序的奇怪功能。 我的主要功能如下所示:

int main(void)

{
    char *example = "index.html";
    regex_t REGEXhtml;
    int mond = 1;
    if(regcomp(&REGEXhtml, ".html", 0)){printf("REGEX error 1"); return -1;}
    mond = regexec(&REGEXhtml, example, 0, NULL, 0);
    if(!mond) {printf("FOUND HTML");}
    printf("%i", mond);

    //......server code ........
}

由于某种原因,在编译后执行此代码时,打印语句将从不打印出来,我的程序似乎会无限空闲。这是没有上述代码的预期行为,因为我的服务器将在终端中空闲并等待连接,然后将其记录到终端。 出乎意料的是,该程序不只是挂在那里。当有人连接到我的服务器时,printf 语句会按应有的方式打印出来,然后是我的服务器记录 printf 语句。

由于这与我目前对编程的理解背道而驰,因此我对这个问题进行了一些研究,并从man page 中发现了以下内容:

│regcomp(), regexec() │ 线程安全 │ MT-Safe locale

属性链接将其描述为含义:

   locale Functions annotated with locale as an MT-Safety issue read
          from the locale object without any form of
          synchronization.  Functions annotated with locale called
          concurrently with locale changes may behave in ways that
          do not correspond to any of the locales active during
          their execution, but an unpredictable mix thereof.

这是否准确地解释了上述行为?我很困惑拥有这些功能似乎会延迟我的打印语句的执行,尤其是最后一个。 如果该描述是相关的,那么在执行和编译期间究竟发生了什么技术细节?

编辑:所以下面的 DannyNiu 修正了我的简单错误,但我仍然对 MT-Safety 语言环境的示例及其对代码其他部分的影响感兴趣。如果有人有示例或解释链接,请在下面发布/评论

【问题讨论】:

    标签: c regex printf posix flush


    【解决方案1】:

    stdout(因此printf)是完全缓冲的,除非libc 检测到它正在输出到终端窗口,在这种情况下它是行缓冲的。

    尝试在输出字符串的末尾添加换行符,或添加fflush 调用。

    【讨论】:

    • 哇!有了这样的答案,我几乎感到尴尬。我不知何故不知道这是 printf() 的运作方式,这似乎是我问题的简单答案
    • 没关系,一开始我也对 POSIX 中的定义方式感到惊讶。
    • (a) 根据 C 2018 7.21.3 3,缓冲是流的属性,而不是 printf。例如,即使使用了 putcharfwrite,也会发生这种情况,而不仅仅是printf。 (b) C 标准中的规则是,标准输入和标准输出在默认情况下是完全缓冲的(可以在程序中更改)当且仅当无法确定流不引用交互式设备时。 (这与答案中的陈述不同,因为它允许流无缓冲,并且在检测不确定时的行为。)
    • @EricPostpischil 我刚刚注意到错误(a),并进行了相应的修改。我不确定如何解决 (b),希望您提出建议。
    【解决方案2】:

    编辑:所以下面的 DannyNiu 修正了我的简单错误,但我仍然对 MT-Safety 语言环境的示例及其对代码其他部分的影响感兴趣。如果有人有示例或解释链接,请在下面发布/评论

    Locale 专为程序的文本输入和输出的国际化和本地化而设计。

    一个进程有一个与之关联的全局语言环境,这个本地环境通常应该由主线程设置。对于多线程程序,通常不需要在辅助线程(非主线程)中更改语言环境,因为大多数情况下,程序仅以一种语言与用户交互。

    但也有例外,例如在加载以其他语言环境编码的文件时。在这种情况下,语言环境对象会看到它们的用途。

    例如,不区分大小写的字符串比较函数strcasecmp(3)strcasecmp_l(3) 依赖于区域设置,但strcasecmp_l(3) 可以采用区域设置对象(避免依赖于全局状态),这允许它在一个与主线程不同的语言环境。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      • 1970-01-01
      • 2013-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多