【问题标题】:Segmentation fault with strlen when not ever using strlen?不使用strlen时strlen的分段错误?
【发布时间】:2016-03-25 00:51:35
【问题描述】:

我有一些代码,它获取一个文件,将每一行读入一个新的字符串数组(并向每个字符添加 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 应该是int,否则while (c != EOF) 永远不会是false。您还将为每个 char 创建一个新数组,而不是为每个新字符串。
  • 看起来你在 for 循环中的条件只需要 j &lt; ROWi &lt; COL
  • 您的while (c != EOF) 循环错误。见stackoverflow.com/questions/5431941/…
  • 128 添加到字符串中的每个char 然后尝试使用"%s" 打印它不会打印出可读的内容。

标签: c arrays string segmentation-fault strlen


【解决方案1】:

之后

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

你应该

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

因为strlen 以阅读0 结束。

【讨论】:

  • 或者使用calloc() 或将分配的第一个(或最后一个)字节设置为0。将整个数组设置为零通常是一个很好的简单做法,但坦率地说,它很少需要
【解决方案2】:

这里实际上有几个错误:

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

  2. fgetc一返回就检查结果是否为EOF

  3. 您正在为每行的每个字符分配一个新的temp_array,而不是为每行分配一次。这需要上移到包含循环中。

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-14
      相关资源
      最近更新 更多