简体   繁体   English

没有使用strlen时strlen的分段错误?

[英]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. 我有一些代码,它接受一个文件,将每一行读入一个新的字符串数组(并为每个字符添加128),然后将每个数组分配到一个指针数组,然后打印每个数组。 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? 但我从来没有在我的代码中调用strlen?

#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); print_strings您使用printf("%s", str);打印字符串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 . 您需要将终止空字节添加到您读取的字符串 - 或者您不能使用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. 你遇到崩溃的原因是你的printf似乎首先检查字符串的长度(使用strlen )然后再打印出来。 strlen increments the char pointer until it reads a null byte. strlen递增char指针,直到它读取空字节。 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. 由于字符串中没有任何内容,因此strlen读取缓冲区并最终在内存中的某处读取空字节,或者如果不允许读取该内存则崩溃。

There are actually several bugs here: 实际上有几个错误:

  1. In read_file , c is initially undefined when first compared to EOF . read_filec首先在与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 . 你应该在它返回时检查fgetc的结果,看它是否是EOF

  3. You are allocating a new temp_array for each character of each row, rather than once for each row. 您为每行的每个字符分配一个新的temp_array ,而不是为每一行分配一次。 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 . print_strings ,您正在遍历行,因此您应该将循环索引与ROW进行比较,而不是COL

  5. When printing a row, you are using %s in a printf . 打印行时,您在printf中使用%s 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). 您可以强制它们,通过分配一个额外的字符并在其中存储'\\0' ,或者您可以在格式说明符中包含一个长度字段来限制长度(您可以使用*将其作为参数传递)。

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 . 因为strlen0读取结束。

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

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