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

strtol、strtod是否不安全?

  •  14
  • user102008  · 技术社区  · 15 年前

    看来 strtol() strtod() 有效地允许(并强制)您在字符串中丢弃常量:

    #include <stdlib.h>
    #include <stdio.h>
    
    int main() {
      const char *foo = "Hello, world!";
      char *bar;
      strtol(foo, &bar, 10); // or strtod(foo, &bar);
      printf("%d\n", foo == bar); // prints "1"! they're equal
      *bar = 'X'; // segmentation fault
      return 0;
    }
    

    如上所述,我自己没有进行任何石膏。然而 strtol() 基本上投我的 const char * 变成 char * 对我来说,没有任何警告或任何事情。(事实上,它不允许你打字 bar 作为一个 常量字符*

    4 回复  |  直到 15 年前
        1
  •  14
  •   Adam Rosenfield    15 年前

    我猜是因为另一种选择更糟糕。假设原型更改为添加 const

    long int strtol(const char *nptr, const char **endptr, int base);
    

    现在,假设我们要分析一个非常量字符串:

    char str[] = "12345xyz";  // non-const
    char *endptr;
    lont result = strtol(str, &endptr, 10);
    *endptr = '_';
    printf("%s\n", str);  // expected output: 12345_yz
    

    但是当我们试图编译这段代码时会发生什么呢?编译器错误!这很不直观,但不能隐式地转换 char ** const char ** . 见 C++ FAQ Lite 详细解释原因。从技术上讲,C++是有问题的,但是对于C/C++中的C.,这些参数同样有效,只允许从“指针”转换为“指针”。 类型 “to”指针指向 常数 “在最高级别:您可以执行的转换来自 煤焦** char * const * ,或等效于“指针到(指针到 char )“to”指针指向( 常数 指向 烧焦 )".

    因为我猜想解析一个非常量字符串比解析一个常量字符串更有可能,所以我将继续假设这一点 常数 -不太可能的情况下的不正确性比将常见情况作为编译器错误更可取。

        2
  •  7
  •   Steve Jessop    15 年前

    是的,其他功能也有相同的“const-laimination”问题(例如,strchr、strstrstr等)。

    strchr(const char*, int)

    const char* strchr(const char* s, int c);
          char* strchr(      char* s, int c);
    

    当然,在C语言中,不能同时使用相同名称的两个const-correct版本,因此会得到const-correct版本。

    char** const char** (与超载的情况一起)解释了C,但是我不太清楚C++过载会有什么问题:

    long strtol(const char*, const char**, int);
    
        3
  •  1
  •   Jonathan Leffler    15 年前

    strtol() 不会修改字符串。

    如何处理返回的指针是您的事情。

    是的,它可以被视为一种类型的安全违规行为;C++可能会做不同的事情(尽管我可以说,ISO/IEC 1488—1998定义) <cstdlib>

        4
  •  1
  •   Joshua    15 年前

    我有一个编译器,它在C++模式编译时提供:

    extern "C" {
    long int strtol(const char *nptr, const char **endptr, int base);
    long int strtol(char *nptr, char **endptr, int base);
    }
    

    显然,这两者都解析为相同的链接时间符号。

    推荐文章