Finlandia_C Finlandia_C - 3 months ago 27
C Question

Segmentation fault with strlen when not ever using strlen?

I have some code which takes a file, reads each line into a new string array (and adds 128 to each character), then assigns each array into an array of pointers, then prints each array. When trying to run the code I get an error stating a segmentation fault due to:

strlen () at ../sysdeps/x86_64/strlen.S:106
106 ../sysdeps/x86_64/strlen.S: No such file or directory.


But I never actually call strlen inside my code?

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define ROW 10
#define COL 40
#define ARGS 2
#define FLIP_VALUE 128

char** read_file (char* argv[], char **array_pointers);
char* new_array (void);
void print_strings (char** array_pointers);

int main(int argc, char* argv[])
{
char **array_pointers = NULL;
if (argc == ARGS)
{
array_pointers = read_file(&argv[1], array_pointers);
print_strings(array_pointers);
}
return 0;
}

char** read_file (char* argv[], char **array_pointers)
{
FILE* file_name;
int i = 0, j = 0;
char c;
char *temp_array;
array_pointers = malloc(sizeof(char*) * ROW);
file_name = fopen(argv[0], "r");
assert(file_name);
if (file_name) /* if file is not null */
{
while (c != EOF) /* while not equal to end of file */
{
for (j = 0; j < ROW; j++) /* for each row */
{
temp_array = new_array(); /* generate a new array for each new string (row) */
for (i = 0; i < COL; i++) /* for each char in a row */
{
c = fgetc(file_name);
temp_array[i] = c + FLIP_VALUE;
}
array_pointers[j] = temp_array; /*assign array pointers to point at each new temp_array */
}
}
}
return array_pointers;
}

char* new_array (void)
{
char* temp;
temp = malloc(sizeof(char) * COL);
assert(temp);
return temp;
}

void print_strings (char** array_pointers)
{
int i = 0;
for (i = 0; i < COL; i++)
{
printf("%s\n",array_pointers[i]);
}
}


The full stack trace reads as:

#1 0x00007ffff7a84e3c in _IO_puts (str=0x0) at ioputs.c:36
result = -1
len = <optimised out>
#2 0x0000000000400806 in print_strings (array_pointers=0x602010)
at array_of_string_arrays.c:65
i = 10
#3 0x00000000004006a1 in main (argc=2, argv=0x7fffffffdff8)
at array_of_string_arrays.c:19
array_pointers = 0x602010

Answer Source

There are actually several bugs here:

  1. In read_file, c is initially undefined when first compared to EOF. Do you even need this outer loop?

  2. You should check the result of fgetc as soon as it returns to see if it's EOF.

  3. You are allocating a new temp_array for each character of each row, rather than once for each row. This needs to be moved up into the containing loop.

  4. In print_strings, you are iterating over the rows so you should compare the loop index to ROW, not COL.

  5. When printing a row, you are using %s in a printf. You can't do that, since there is no guarantee that the characters in a row are null-terminated. You could force them to be, by allocating an additional character and storing '\0' in it, or you could include a length field in the format specifier to limit the length (you can use * to pass it as an argument).

I suspect the last bug is the one that's causing the segmentation fault.