不使用 strlen 时会出现 strlen 分段错误吗?

问题描述 投票:0回答:4

我有一些代码,它接受一个文件,将每一行读入一个新的字符串数组(并向每个字符添加 128),然后将每个数组分配到一个指针数组中,然后打印每个数组。当尝试运行代码时,我收到一条错误,指出分段错误,原因是:

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

但我实际上从未在代码中调用过 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]);
    }
}

完整的堆栈跟踪如下:

#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
c arrays string segmentation-fault strlen
4个回答
5
投票

print_strings
中,您使用
printf("%s", str);
打印字符串。这要求字符串以空字符结尾。如果您正在读取普通文本文件,则您写入的字符串不会以空字符结尾。您需要将终止空字节添加到您读取的字符串中 - 否则您无法使用
printf

崩溃的原因是你的

printf
似乎在打印之前首先检查字符串的长度(使用
strlen
)。
strlen
递增 char 指针,直到读取空字节。由于字符串中没有任何内容,因此
strlen
会读取缓冲区,最后要么读取内存中某处的空字节,要么在不允许读取该内存的情况下崩溃。


4
投票

这里实际上有几个bug:

  1. read_file
    中,当第一次与
    c
    比较时,
    EOF
    最初是未定义的。你还需要这个外循环吗?

  2. 你应该在

    fgetc
    返回后立即检查它是否是
    EOF

  3. 您为每行的每个字符分配一个新的

    temp_array
    ,而不是为每行分配一次。这需要向上移动到包含循环中。

  4. print_strings
    中,您正在迭代行,因此您应该将循环索引与
    ROW
    进行比较,而不是
    COL

  5. 打印一行时,您在

    %s
    中使用
    printf
    。您不能这样做,因为不能保证行中的字符以空终止。您可以通过分配额外的字符并在其中存储
    '\0'
    来强制它们,或者您可以在格式说明符中包含一个长度字段来限制长度(您可以使用
    *
    将其作为参数传递)。

我怀疑最后一个错误是导致分段错误的原因。


3
投票

之后

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

你应该

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

因为

strlen
通过阅读
0
结束。


0
投票

我意识到这个问题是很久以前的问题了,但我最近遇到了同样的问题。希望我的回答对某人有所帮助!

这就是我解决问题的方法: 在调试过程中,我没有看到监视列表中有 strlen(x) 。因此,当 x 不可访问时,就会导致分段错误。

简单地在调试期间从监视列表中删除 strlen() 的任何实例解决了我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.