【问题标题】:Segmentation fault occurring in for loop (no body statements executed) Cfor循环中发生分段错误(未执行主体语句)C
【发布时间】:2017-06-30 11:12:49
【问题描述】:

我正在尝试编写一个程序将十六进制数转换为十进制数,然后打印十进制值。我面临的问题是我的 for 循环导致分段错误。

  printf("no segmentation fault so far..."); /*this printed*/
  for (i=0; (c=getchar()) != '\n'; i++) {
    printf("no segmentation fault after entering for loop"); /*this didn't print*/

我知道这一点,因为正如您从我的代码中看到的,在 for 循环运行之前的所有代码但主体没有执行。可能没有满足 for 循环测试用例,因此它被跳过。为了测试这一点,我还将 printf 语句放在程序的其他部分。但是,只执行了 for 循环上方的那个。如果有帮助,这是我的完整代码:

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#define MAXLEN 100

int htoi(char *s, int lim);
void copy(char *to, char *from);

int main(void) {
  char *hexArray = (char *)malloc(MAXLEN);
  htoi(hexArray, MAXLEN);
  return 0;
}

int htoi(char s[], int lim) {
  double decOutput;
  int i = 0;
  int c;
  int size = MAXLEN;
  printf("no segmentation fault so far...");
  for (i=0; (c=getchar()) != '\n'; i++) {
    printf("no segmentation fault after entering for loop");
    if (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
      if(i >= size - 1) {
        size = size + MAXLEN;
        char *tmp = (char *)malloc(size);
        copy(tmp, s);
        free(s);
        s = tmp;
        printf("Buffer size increased to %d\n", size);
      }
      s[i] = c;
    }
    else {
      printf("INVALID INPUT!!! Decimal output may be inaccurate.");
    }
  }

  printf("exited loop");

  for(i = 0; s[i] != '\0'; i++) {
    printf("entered second for loop");
    if (s[i] != '0' || (s[i+1] != 'x' && s[i+1] != 'X')) {
      double y = pow(16, (double)i);
      double x = s[i];
      decOutput = decOutput + pow(x, y);
    }
  }
  printf("%s", decOutput);

  return decOutput;
}

void copy(char *to, char *from) {
  int i = 0;
  while((to[i] = from[i]) != '\0') {
    i++;
  }
}

【问题讨论】:

  • 请记住,输出到stdoutprintf 写入)默认情况下是行缓冲。这意味着在没有任何换行符的情况下调用 printf 只会添加到缓冲区中。要找到崩溃的实际位置,您应该使用调试器
  • 在不相关的说明中,您知道isdigit,但不知道isalpha 或更贴切的isalnum
  • 在打印字符串的末尾放一个换行符,这应该会刷新输出缓冲区:printf("no segmentation fault after entering for loop\n"); 你应该会看到打印出来的。您应该在所有调试输出 printf 字符串的末尾有一个换行符。但是学习使用调试器将是最可靠的定位故障的方法。
  • s 不会以空值结尾。你也可以使用isxdigit
  • for (i=0; (c=getchar()) != '\n'; i++) {} --> for (i=0; (c=getchar()) != '\n' &amp;&amp; c != EOF; i++) {} 避免无限循环,因为getchar() 在极少数发生错误时返回EOF

标签: c


【解决方案1】:

您可以使用此命令从 gcc 编译器中捕获错误或有用的警告。

gcc t.c -o t -l m  -Wall -Wextra 

我编译了你的代码,gcc 产生了这个输出。

t.c: In function ‘htoi’:
t.c:54:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘double’ [-Wformat=]
   printf("%s", decOutput);
          ^
t.c:19:24: warning: unused parameter ‘lim’ [-Wunused-parameter]
 int htoi(char s[], int lim) {

使用printf 打印双变量的正确方法是 将printf("%s", decOutput); 更改为printf("%f", decOutput); 专注于double 格式说明符是%f in printf()。 (阅读true way of printing a double )

通过添加此更改并附加 htoi 函数末尾的简单消息状态,您的代码将转换为:

//getchar() != EOF

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>

#define MAXLEN 100

int htoi(char *s, int lim);
void copy(char *to, char *from);

int main(void) {
  char *hexArray = (char *)malloc(MAXLEN);
  htoi(hexArray, MAXLEN);
  return 0;
}

int htoi(char s[], int lim) {
  double decOutput;
  int i = 0;
  int c;
  int size = MAXLEN;
  printf("no segmentation fault so far...");
  for (i=0; (c=getchar()) != '\n'; i++) {
    printf("no segmentation fault after entering for loop");

    if (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
      if(i >= size - 1) {
        size = size + MAXLEN;
        char *tmp = (char *)malloc(size);
        copy(tmp, s);
        free(s);
        s = tmp;
        printf("Buffer size increased to %d\n", size);
      }
      s[i] = c;
    }
    else {
      printf("INVALID INPUT!!! Decimal output may be inaccurate.");
    }
  }

  printf("exited loop");

  for(i = 0; s[i] != '\0'; i++) {
    printf("entered second for loop");
    if (s[i] != '0' || (s[i+1] != 'x' && s[i+1] != 'X')) {
      double y = pow(16, (double)i);
      double x = s[i];
      decOutput = decOutput + pow(x, y);
    }
  }

  printf("%f", decOutput);

  printf("\nend htoi\n");
  return decOutput;
}

void copy(char *to, char *from) {
  int i = 0;
  while((to[i] = from[i]) != '\0') {
    i++;
  }
}

继续努力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-14
    相关资源
    最近更新 更多