K& R atoi-一般内存泄漏

时间:2016-02-05 08:51:40

标签: c atoi kernighan-and-ritchie

我正在关注K& R第二版示例以学习C和编码,因为我认为这是正确的做事方式。无论如何,当我在编译后运行该程序时程序卡住了。我使用valgrind来执行编译脚本。

#include <ctype.h>

int atoi(char s[])
{
    int i, n, sign;
    for(i = 0; isspace(s[i]); i++)
        ;
    sign = (s[i] == '-')? -1 : 1;
    if (s[i] == '+'|| s[i] == '-')
        i++;
    for (int n = 0; isdigit(s[i]); n++)
        n = 10 * n + (s[i]-'0');
    return sign * n;
}

int main()
{
    char input[] = "       -12345";
    atoi(input);
}
# vaibhavchauhan at startup001 in ~/Documents/Projects/K-R on git:master x [0:43:36]
$ valgrind ./atoi-general
==8075== Memcheck, a memory error detector
==8075== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==8075== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==8075== Command: ./atoi-general
==8075==
^C==8075==

3 个答案:

答案 0 :(得分:3)

在第二个循环中,您正在迭代n,但您使用i进行计算和计算。这导致你观察到的无限循环。要解决此问题,请始终使用i作为索引:

int atoi(char s[])
{
    int i, sign, n;
    for(i = 0; isspace(s[i]); i++)
        ;
    sign = (s[i] == '-')? -1 : 1;
    if (s[i] == '+'|| s[i] == '-')
        i++;
    for (n = 0; isdigit(s[i]); i++)
        n = 10 * n + (s[i]-'0');
    return sign * n;
}

请注意,索引应该具有类型size_t,而不是int,因为后者可能不足以索引每个数组。为此,类型int的索引很好。

答案 1 :(得分:3)

注意到,第二个循环中的索引不正确。

for(int n = 0; isdigit(s[i]); n++)
    n = 10 * n + (s[i]-'0');

这应该是 - 请注意你应该不要重新初始化第二个循环中的索引i,因为它应该是第一个循环的剩余值(因为你已经跳过了白色)空间和标志)。

for( ; isdigit(s[i]); i++ )
    n = 10 * n + (s[i]-'0');

答案 2 :(得分:3)

可以改进K&amp; R示例的可读性和性能。存在以下问题:

  • 您不能像标准的lib函数一样命名自己的函数。 stdlib.h中存在atoi
  • 对传递的参数使用const正确性。
  • 多个循环和迭代器很难读取和维护,这导致了问题中的错误。理想情况下,应该只有一个迭代器。可以说,这个错误是由原始程序员引起的,因为他们编写了不可维护的,邋code的代码。
  • 类型size_t应该用于迭代器,而不是int
  • 如果迭代器也有一个有意义的名字也不会有害。 n是迭代器的一个非常糟糕的名字!在C编程中,n具有特殊含义,即描述容器中的项目数。
  • 为了便于阅读,可能还有性能,指针参数可以用作迭代器。然后我们不需要首先发明所有这些局部迭代器变量。
  • 为符号使用bool变量以提高可读性。
  • 无需检查当前字符是否为-两次。
  • 每次声明后都要使用大括号,以防止致命的错误,例如Apple goto失败。
#include <ctype.h>
#include <stdbool.h>


int my_atoi (const char* str)
{
  while(isspace(*str))
  {
    str++;
  }

  bool sign = false;
  if(*str == '-')
  {
    sign = true;
    str++;
  }
  else if(*str == '+')
  {
    str++;
  }

  int result = 0;
  while(isdigit(*str))
  {
    result = 10*result + *str - '0';
    str++;
  }

  if(sign)
  {
    result = -result;
  } 

  return result;
}