2

Hello Stack Exchange community,

I have a function that reads a CSV file into a gsl_matrix and then returns a pointer to the matrix. The function executes without error, however the program exits with SIGABRT when executing printf with a constant string after the function returns. I've tried:

  • Changing the string that is printed
  • Abstracting the string to be a format followed by a char

Neither worked, however I discovered that placing a printf() before the call of the function prevents this error (commented out in main() below). I'm compiling with gcc 5.4.0 on Ubuntu 16.04. Calling malloc_stats() before this line shows that I'm using approximately 6kB of the heap. The LLDB output shown below illustrates exactly which line causes the error in print_matrix().

Process 10955 stopped
* thread #1: tid = 10955, 0x000000000040114b main`print_matrix(matrix=0x0000000000604010) + 21 at main.c:88, name = 'main', stop reason = step over
    frame #0: 0x000000000040114b main`print_matrix(matrix=0x0000000000604010) + 21 at main.c:88
   85   static void print_matrix(gsl_matrix * matrix)
   86   {
   87     for (int i = 0; i < matrix->size1; i++) {
-> 88       printf("[");
   89       for (int j = 0; j < matrix->size2; j++) {
   90         printf("%g, ", gsl_matrix_get(matrix, i, j));
   91       }
(lldb) 
Process 10955 stopped
* thread #1: tid = 10955, 0x00007ffff708d428 libc.so.6`__GI_raise(sig=6) + 56 at raise.c:54, name = 'main', stop reason = signal SIGABRT
    frame #0: 0x00007ffff708d428 libc.so.6`__GI_raise(sig=6) + 56 at raise.c:54

The code shown below is the main function, which resides in main.c:

int main(int argc, char * argv[]) {
  /* printf("This is the fix.\n"); */
  gsl_matrix * matrix2 = read_tuples_csv("data/12AX7-Data.csv", 3);
  print_matrix(matrix2);
}

The following code is the function read_tuples_csv(), which resides in util.c. The function takes the path of the file to read and the size of the tuples to parse. I suspect that the problem is in this function, but no amount of proofreading or debugging has been able to reveal the error in my semantics thus far.

gsl_matrix * read_tuples_csv(const char * filename, size_t n)
{
  FILE * file;
  if ((file = fopen(filename, "r")) == NULL || n <= 0)
    return NULL;

  List * list = malloc(sizeof(List));
  list_init(list, free);

  double * arr;
  while (!feof(file)) {
    arr = calloc(n, sizeof(double));
    char *line = NULL, *scratch;
    size_t n = 0;
    if (getline(&line, &n, file) == -1) goto error_exit;
    line = strtok_r(line, ",", &scratch);

    int i = 0;
    do {
      int ret = sscanf(line, "%lf", &arr[i]);
      if (ret <= 0) fprintf(stderr, "Something happened:\nline:\t%s", line);
      i++;
    } while ((line = strtok_r(NULL, ",", &scratch)) != NULL && i < n);

    free(line);
    line = NULL;
    if (list_insnxt(list, list_tail(list), arr) != 0)
      goto error_exit;
  }
  fclose(file);
  file = NULL;

  gsl_matrix * matrix = gsl_matrix_alloc(list_size(list), n);
  int i = 0;
  while (list_size(list) > 0) {
    double * vector;
    list_remnxt(list, NULL, (void **)&vector);
    for (int j = 0; j < n; j++) {
      gsl_matrix_set(matrix, i, j, vector[j]);
    }
    i++;
  }

  list_dest(list);
  free(list);

  return matrix;

 error_exit: {
    if (file != NULL) fclose(file);
    list_dest(list);
    free(arr);
    free(list);
    return NULL;
  }
}
amateurece
  • 113
  • 1
  • 9
  • [Please see Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/q/5431941/2173917) – Sourav Ghosh Sep 05 '17 at 15:53
  • I don;t see any error checking for `malloc()` and family!! – Sourav Ghosh Sep 05 '17 at 15:54
  • _Questions seeking debugging help (why isn't this code working?) must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a [mcve]._ – Sourav Ghosh Sep 05 '17 at 15:54
  • @SouravGhosh thanks for catching those. I'm immediately working on fixing those problems, however the problem persists. – amateurece Sep 05 '17 at 15:58
  • Also, please inform me how to refine my question. I attempted to provide the minimal example, with the maximum description of the problem. I can include the output from the function with the printf "fix" if that would help. – amateurece Sep 05 '17 at 16:01
  • change `while (!feof(file))` to `while (getline(&line, &n, file) != -1)`. – Paul Ogilvie Sep 05 '17 at 16:05
  • Thanks to the both of you, removing feof() fixed the problem. Lesson learned, on I/O, I suppose. If one of you would repost your comment as an answer, I can accept it as fixing the problem. Thank you again. – amateurece Sep 05 '17 at 16:26

2 Answers2

0

The problem could be due to:

printf("%g, ", gsl_matrix_get(matrix, i, j));

Because you are trying to printf a double but your function is returning a gsl_matrix pointer.

Also it's considered better form to printf("%s", "[") or printf("%c", '[') rather than printf("[").

Mike Gleason
  • 3,439
  • 1
  • 14
  • 7
  • *Also it's considered better form to `printf("%s", "[")` or `printf("%c", '[')` rather than `printf("[")`.* By who? – Andrew Henle Sep 05 '17 at 19:40
0

Thanks to @SouravGhosh and @PaulOgilvie for providing the answer. The problem lay in my use of feof() as a switch for the while loop. This is poor practice, and in many cases (this one included) it caused undefined behavior. Why this would cause the line

printf("[");

To fail is beyond me. It appears to be a buffer overflow of stdout, but I tested this by calling fflush() on stdout before the failure, and the problem was not remedied. If anyone is able to identify the exact cause of the problem, I would appreciate it. Also thanks to @SouravGhosh for reminding me that I forgot to check the return value of calloc().

amateurece
  • 113
  • 1
  • 9