简体   繁体   English

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

[英]Segmentation fault when passing pointer to function

I am getting a segmentation fault when I call my getField(char *line, int field) function in my while loop and I'm not sure why. 我在while循环中调用getField(char * line,int field)函数时遇到分段错误,我不确定为什么。 I'm trying to pass a line to the function and a column number so that I can grab specific columns from each line in a csv file and print them to the screen. 我试图将一行传递给该函数和一列号,以便可以从csv文件中的每一行中获取特定的列并将其打印到屏幕上。 Thanks for input. 感谢您的输入。

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);
}

One obvious error is that you have an infinite loop here, and you will eventually access illegal memory. 一个明显的错误是您在这里存在无限循环,最终您将访问非法内存。

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

You are not modifying column at all, so your loop cannot possibly end. 您根本不需要修改column ,因此循环可能无法结束。 column will not update itself when you update field , so you will have to update it if you want it to update. 当您更新fieldcolumn将不会自行更新,因此,如果要更新它,则必须对其进行更新。

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

Note on debugging segfaults using printf . 关于使用printf调试segfaults的注意事项。

The function printf prints to stdout and stdout likes to buffer output. 函数printf打印到stdoutstdout喜欢缓冲输出。 This means that sometimes if you try to find a segfault by moving a print statement down your code until it fails to print, you will misunderstand where the segfault it happening. 这意味着有时候,如果您尝试通过将一条打印语句向下移动代码直到其无法打印,从而找到一个段错误,您将会误解它在哪里发生。 In particular, a printf line that appears before the line that actually contains the segfault may not print even if you might expect it to. 特别是,实际上包含该段错误的行之前出现的printf行可能不会打印,即使您希望这样做。

If you want to use this strategy (instead of gdb ), you can force it to print by using fflush(stdout); 如果要使用此策略(而不是gdb ),则可以使用fflush(stdout);强制其打印fflush(stdout); immediately after your debugging printf . 在调试printf之后立即进行。

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

In following line: 在以下行中:

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

you are using the %s format specifier but you are passing a char as argument. 您正在使用%s格式说明符,但要传递一个char作为参数。

You probably want this ( %c format specifier fot printing a char ): 您可能想要这样( %c格式说明符,然后打印char ):

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

You are accessing out of bounds of the array in the function getField because the while loop never exits. 您正在访问函数getField数组的边界,因为while循环永远不会退出。 This invokes undefined behaviour and most likely program crash due to segfault which is what is happening in your case. 这会引起未定义的行为,并且很可能是由于段错误(在您的情况下发生)而导致程序崩溃。 I suggest the following changes to your program. 我建议对程序进行以下更改。

#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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM