将指针传递给函数时出现分段错误

时间:2014-04-16 05:41:26

标签: c

当我在while循环中调用getField(char * line,int field)函数时,我遇到了分段错误,我不知道为什么。我正在尝试将一行传递给函数和列号,以便我可以从csv文件中的每一行中获取特定列并将其打印到屏幕上。感谢您的投入。

void getField(char *line, int field);

int main(int argc, char *argv[]) {

  if(argc < 3) {
    fprintf(stderr, "Too few arguments \"%s\".\n", argv[0]);
  }

  if(atoi(argv[1]) < 1) {
    fprintf(stderr, "First argument must be >= 1 \"%s\".\n", argv[1]);
  }
  FILE *fp = fopen(argv[2], "r");
  if(fp == NULL)
    fprintf(stderr, "Cannot open file %s\n", argv[0]);
  char buf[80];
  while(fgets(buf, 80, fp) != NULL) {
    getField(buf, atoi(argv[1]);  // seg fault is happening here
  }

  return 0;
}

void getField(char *line, int field) {
  printf("here2");
  //char *ln = line;
  int column = field - 1;
  int idx = 0;
  while(column) {
    //printf("here");
    if(line[idx] == ',') field--;
    idx++;
  }

  for(int j = idx; ; ++j) {
    if(line[j] == ',') break;
    printf("%s", line[j]);
  }
  printf("\n");
  printf("%d", idx);
}

4 个答案:

答案 0 :(得分:4)

一个明显的错误是你在这里有一个无限循环,你最终会访问非法内存。

while(column) {
     //printf("here");
    if(line[idx] == ',') field--;
    idx++;
}

您根本不修改column,因此您的循环无法结束。 更新column时,field不会自行更新,因此如果您希望更新,则必须对其进行更新。

while(column) {
     //printf("here");
    if(line[idx] == ',') field--;
    idx++;
    column = field - 1;
}

有关使用printf调试段错误的说明。

函数printf打印到stdoutstdout喜欢缓冲输出。这意味着,有时如果您尝试通过向代码移动打印语句直到无法打印来查找段错误,您将会误解它发生的段错误。特别是,在实际包含段错误的行之前出现的printf行可能无法打印,即使您可能期望它。

如果您想使用此策略(而不是gdb),可以在调试fflush(stdout);后立即使用printf强制打印。

答案 1 :(得分:1)

while(column) {
        //printf("here");
        if(line[idx] == ',') column--;  // Changed field-- to column--
                idx++;
}

答案 2 :(得分:0)

以下一行:

printf("%s", line[j]);

您使用的是%s格式说明符,但是您传递了char作为参数。

你可能希望这个(%c格式说明符打印char):

printf("%c", line[j]);

答案 3 :(得分:0)

您正在函数getField中访问数组的边界,因为while循环永不退出。这会调用未定义的行为,并且很可能由于段错误导致程序崩溃,这就是您的情况。我建议对您的计划进行以下更改。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void getField(char *line, int field);

int main(int argc, char *argv[]) {
  if(argc < 3) {
    fprintf(stderr, "Too few arguments \"%s\".\n", argv[0]);
    return 1; // end the program
  }

  if(atoi(argv[1]) < 1) {
    fprintf(stderr, "First argument must be >= 1 \"%s\".\n", argv[1]);
    return 1; // end the program
  }

  FILE *fp = fopen(argv[2], "r");
  if(fp == NULL) {
    fprintf(stderr, "Cannot open file %s\n", argv[0]);
    return 1; // end the program
  }

  char buf[80];
  while(fgets(buf, 80, fp) != NULL) {
    getField(buf, atoi(argv[1]));  // seg fault is happening here
  }

  return 0;
}

void getField(char *line, int field) {
  int len = strlen(line);
  char temp[len + 1];
  strcpy(temp, line);

  int count = 0;
  char ch = ',';
  char *p = temp;
  char *q = NULL;
  while(count < field - 1) {
    q = strchr(p, ch);
    if(q == NULL) {
      printf("error in the value of field\n");
      return;
    }
    count++;
    p = q + 1;
  }
  q = strchr(p, ch);
  if(q != NULL)
    *q = '\0';
  else 
    temp[len-1] = '\0';

  printf("%s\n", p);
}