简体   繁体   中英

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

In print_strings you print the string using printf("%s", str); . This requires the string to be null terminated. The strings you write are not null terminated if you are reading an ordinary text file. You need to add the terminating null byte to the strings you read - or you cannot use printf .

The reason you get a crash is that your printf seems to check first how long the string is (using strlen ) before printing it out. strlen increments the char pointer until it reads a null byte. Since you don't have any in the string, strlen reads past the buffer and finally either reads a null byte somewhere in memory or crashes if it is not allowed to read that memory.

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.

After

temp = malloc(sizeof(char) * COL); 

you should

memset(temp,0,sizeof(char) * COL);

because strlen is end by reading 0 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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