atoi多线程安全吗? [英] Is atoi multithread safe?

查看:240
本文介绍了atoi多线程安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

创建多线程程序时遇到错误.使用gdb进行调试时,atoi函数会引发错误.请帮助,atoi多线程是否不安全?如果是,那有什么替代方法?

I am experiancing some error while creating a multithreaded program. While using gdb to debug, the atoi function is throwing error. Please help, is atoi multithread unsafe and if so, what are the alternatives?

推荐答案

很容易实现对 atoi() :

Its quite easy to implement a replacement for atoi():

int strToInt(const char *text)
{
  int n = 0, sign = 1;
  switch (*text) {
    case '-': sign = -1;
    case '+': ++text;
  }
  for (; isdigit(*text); ++text) n *= 10, n += *text - '0';
  return n * sign;
}

(关于 ideone 的演示)

(Demonstration on ideone)

替换已经可用的东西似乎没有多大意义.因此,我想提一些有关此的想法.

It doesn't seem to make much sense to replace something which is already available. Thus, I want to mention some thouhgts about this.

可以根据具体的个人要求调整实施方式:

The implementation can be adjusted to the precise personal requirements:

  • 可能会添加整数溢出检查
  • 可能会返回text的最终值(如在strtol()中一样),以检查已处理了多少个字符或进一步解析了其他内容
  • unsigned可能会使用变体(不接受符号).
  • 前面的空格可能会或可能不会被接受
  • 可以考虑使用特殊语法
  • 还有其他一切都超出了我的想象力.
  • a check for integer overflow may be added
  • the final value of text may be returned (as in strtol()) to check how many characters have been processed or to do further parsing of other contents
  • a variant might be used for unsigned (which does not accept a sign).
  • preceding spaces may or may not be accepted
  • special syntax may be considered
  • and anything else beyound my imagination.

将此想法扩展到其他数字类型,例如floatdouble,它变得更加有趣.

Extending this idea to other numeric types like e.g. float or double, it becomes even more interesting.

由于浮点数绝对是本地化的主题,因此必须予以考虑. (关于十进制整数,我不确定可以本地化什么,但即使是这种情况也是如此.)如果实现了具有浮点数语法(例如C语言)的文本文件阅读器,您可能不会忘记将语言环境调整为C,然后再使用 strtod() (使用

As floating point numbers are definitely subject of localization this has to be considered. (Concerning decimal integer numbers I'm not sure what could be localized but even this might be the case.) If a text file reader with floating point number syntax (like in C) is implemented you may not forget to adjust the locale to C before using strtod() (using setlocale()). (Being a German I'm sensitive to this topic, as in the German locale, the meaning of '.' and ',' are just vice versa like in English.)

{ const char *localeOld = setlocale(LC_ALL, "C");
  value = strtod(text);
  setlocale(LC_ALL, localeOld);
}

另一个事实是,考虑语言环境(即使调整为C)似乎也有些昂贵.几年前,我们实现了自己的浮点读取器,以替换 strtod() COLLADA 阅读器( XML文件格式,其中文件经常提供大量的浮点数.

Another fact is, that consideration of locale (even if adjusted to C) seems to be somehow expensive. Some years ago, we implemented an own floating point reader as replacement of strtod() which provided a speed-up of 60 ... 100 in a COLLADA reader (an XML file format where files often provide lots of floating point numbers).

更新:

受到保罗·弗洛伊德(Paul Floyd)的反馈的鼓舞,我很好奇 更快的strToInt().因此,我建立了一个简单的测试套件并进行了一些测量:

Encouraged by the feedback of Paul Floyd, I got curious how faster strToInt() might be. Thus, I built a simple test suite and made some measurements:

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int strToInt(const char *text)
{
  int n = 0, sign = 1;
  switch (*text) {
    case '-': sign = -1;
    case '+': ++text;
  }
  for (; isdigit(*text); ++text) n *= 10, n += *text - '0';
  return n * sign;
}

int main(int argc, char **argv)
{
  int n = 10000000; /* default number of measurements */
  /* read command line options */
  if (argc > 1) n = atoi(argv[1]);
  if (n <= 0) return 1; /* ERROR */
  /* build samples */
  assert(sizeof(int) <= 8); /* May be, I want to do it again 20 years ago. */
  /* 24 characters should be capable to hold any decimal for int
   * (upto 64 bit)
   */
  char (*samples)[24] = malloc(n * 24 * sizeof(char));
  if (!samples) {
    printf("ERROR: Cannot allocate samples!\n"
      "(Out of memory.)\n");
    return 1;
  }
  for (int i = 0; i < n; ++i) sprintf(samples[i], "%d", i - (i & 1) * n);
  /* assert correct results, ensure fair caching, pre-heat CPU */
  int *retAToI = malloc(n * sizeof(int));
  if (!retAToI) {
    printf("ERROR: Cannot allocate result array for atoi()!\n"
      "(Out of memory.)\n");
    return 1;
  }
  int *retStrToInt = malloc(n * sizeof(int));
  if (!retStrToInt) {
    printf("ERROR: Cannot allocate result array for strToInt()!\n"
      "(Out of memory.)\n");
    return 1;
  }
  int nErrors = 0;
  for (int i = 0; i < n; ++i) {
    retAToI[i] = atoi(samples[i]); retStrToInt[i] = strToInt(samples[i]);
    if (retAToI[i] != retStrToInt[i]) {
      printf("ERROR: atoi(\"%s\"): %d, strToInt(\"%s\"): %d!\n",
        samples[i], retAToI[i], samples[i], retStrToInt[i]);
      ++nErrors;
    }
  }
  if (nErrors) {
    printf("%d ERRORs found!", nErrors);
    return 2;
  }
  /* do measurements */
  enum { nTries = 10 };
  time_t tTbl[nTries][2];
  for (int i = 0; i < nTries; ++i) {
    printf("Measurement %d:\n", i + 1);
    { time_t t0 = clock();
      for (int i = 0; i < n; ++i) retAToI[i] = atoi(samples[i]);
      tTbl[i][0] = clock() - t0;
    }
    { time_t t0 = clock();
      for (int i = 0; i < n; ++i) retStrToInt[i] = strToInt(samples[i]);
      tTbl[i][1] = clock() - t0;
    }
    /* assert correct results (and prevent that measurement is optimized away) */
    for (int i = 0; i < n; ++i) if (retAToI[i] != retStrToInt[i]) return 3;
  }
  /* report */
  printf("Report:\n");
  printf("%20s|%20s\n", "atoi() ", "strToInt() ");
  printf("--------------------+--------------------\n");
  double tAvg[2] = { 0.0, 0.0 }; const char *sep = "|\n";
  for (int i = 0; i < nTries; ++i) {
    for (int j = 0; j < 2; ++j) {
      double t = (double)tTbl[i][j] / CLOCKS_PER_SEC;
      printf("%19.3f %c", t, sep[j]);
      tAvg[j] += t;
    }
  }
  printf("--------------------+--------------------\n");
  for (int j = 0; j < 2; ++j) printf("%19.3f %c", tAvg[j] / nTries, sep[j]);
  /* done */
  return 0;
}

我在某些平台上尝试过.

I tried this on some platforms.

Windows 10(64位)上的VS2013,发布模式:

VS2013 on Windows 10 (64 bit), Release mode:

Report:
             atoi() |         strToInt()
--------------------+--------------------
              0.232 |              0.200
              0.310 |              0.240
              0.253 |              0.199
              0.231 |              0.201
              0.232 |              0.253
              0.247 |              0.201
              0.238 |              0.201
              0.247 |              0.223
              0.248 |              0.200
              0.249 |              0.200
--------------------+--------------------
              0.249 |              0.212

cygwin,Windows 10(64位),gcc -std=c11 -O2上的

gcc 5.4.0:

gcc 5.4.0 on cygwin, Windows 10 (64 bit), gcc -std=c11 -O2:

Report:
             atoi() |         strToInt() 
--------------------+--------------------
              0.360 |              0.312 
              0.391 |              0.250 
              0.360 |              0.328 
              0.391 |              0.312 
              0.375 |              0.281 
              0.359 |              0.282 
              0.375 |              0.297 
              0.391 |              0.250 
              0.359 |              0.297 
              0.406 |              0.281 
--------------------+--------------------
              0.377 |              0.289

codingground 上上传并执行的示例
Linux 3.10.0-327.36.3.el7.x86_64上的gcc 4.8.5,gcc -std=c11 -O2:

Sample uploaded and executed on codingground
gcc 4.8.5 on Linux 3.10.0-327.36.3.el7.x86_64, gcc -std=c11 -O2:

Report:
             atoi() |         strToInt() 
--------------------+--------------------
              1.080 |              0.750 
              1.000 |              0.780 
              0.980 |              0.770 
              1.010 |              0.770 
              1.000 |              0.770 
              1.010 |              0.780 
              1.010 |              0.780 
              1.010 |              0.770 
              1.020 |              0.780 
              1.020 |              0.780 
--------------------+--------------------
              1.014 |              0.773 

好吧,strToInt()快了一点点. (没有-O2的情况,它甚至比atoi()慢,但标准库可能也已优化.)

Well, strToInt() is a little bit faster. (Without -O2, it was even slower than atoi() but the standard library was probably optimized too.)

注意:

由于时间测量涉及分配和循环操作,因此可以定性地说明哪一个速度更快.它没有提供量化因素. (要得到一个,测量会变得更加复杂.)

As the time measurement involves assignment and loop operations, this provides a qualitative statement about which one is faster. It doesn't provide a quantitative factor. (To get one, the measurement would become much more complicated.)

由于atoi()的简单性,应用程序必须经常使用它 ,直到它甚至值得考虑开发工作时为止.

Due to the simplicity of atoi(), the application had to use it very often until it becomes even worth to consider the development effort...

这篇关于atoi多线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆