代码之家  ›  专栏  ›  技术社区  ›  SiegeX

如何检测C中字符串文字传递给函数的情况?

  •  5
  • SiegeX  · 技术社区  · 15 年前

    我正在尝试实现Perl的eqiVillant版本 chomp() 我和C语言中的函数遇到了一个角情况,其中作为参数传递的字符串文字将导致分段错误(正确地说是这样)。

    例子 chomp("some literal string\n");

    在C99中是否有一种确定的方法来检测我的函数是否被传递了一个字符串文字以便我可以 return 不想把它裸露出来?

    char* chomp(char *s)
    {
        char *temp = s;
    
        if (s && *s)
        {
            s += strlen(s) - 1;
            if (*s == '\n')
            {
                *s = '\0';
            }
        }
        return temp;
    }
    
    3 回复  |  直到 13 年前
        1
  •  5
  •   Anon.    15 年前

    在c99中,是否有一种确定的方法来检测我的函数是否被传递了一个字符串文本,这样我就可以返回而不必尝试nul-out了?

    你不应该这样做。

    您的API不应该试图为调用者篡改东西,而应该在以后中断。 如果打电话的人违反了规则,他们应该当场查出。

    如果调用方将不可变字符串传递给需要可变字符串的函数,则 应该 节错。其他的都是坏设计。

    (附录:当然,最佳设计是返回调用方负责释放的字符串的副本。)

        2
  •  3
  •   dirkgently    15 年前

    你的 chomp 最好创建一个新字符串并返回它。无法确定是否传递了字符串文本。事实上,我建议使用以下签名 乔普 :

    char *chomp(const char *s); /* do not modify input parameters */
    

    或者,您可以创建两个不同的函数并为客户机记录它们:使用 乔普 对于非文字和 chompl 对于文本字符串。

        3
  •  1
  •   Agnius Vasiliauskas    13 年前

    有一种非常危险/错误的方法=>通常字符串文本存储在只读数据部分中。因此,一种方法是尝试写入目标字符串-if segmentation fault 接收到 signal callback -这意味着您的字符串是文本的,并返回到测试函数 longjmp . 类似:

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <setjmp.h>
    
    static jmp_buf jbuf;
    
    static void catch_segv() {
        longjmp(jbuf, 1);
    }
    
    int isLiteral(char * ptr) {
      if (setjmp(jbuf) == 0)
        return  (*ptr = *ptr, 0);
      else
        return 1;
      }
    
    int main()
    {
        char writableString[] = "some writable string";
    
        signal(SIGSEGV, catch_segv);
    
        printf("is literal = %d\n", isLiteral(writableString));
        printf("is literal = %d\n", isLiteral("read-only string"));
    
        return 0;
    }
    

    但考虑到恢复计划 SIGSEGV 这是非常危险的事情,而且考虑到字符串文本并不总是存储在只读数据部分中,所以强烈建议不要将此解决方案用于生产。