【问题标题】:segmentation fault core dumped Issue with C分段错误核心转储 C 的问题
【发布时间】:2015-06-27 06:32:46
【问题描述】:

我知道以前有人问过这个问题,并且我认为我理解有分段错误意味着我在某处有一个错误的指针。话虽如此,我非常感谢帮助我找出我的错误所在。我有一个头文件和两个源文件,它们是

标题:

#ifndef LINEHOLDER_H_INCLUDED
#define LINEHOLDER_H_INCLUDED



#define DEFAULT 100
#define MAXLEN 256
#define MAXLINES 1024
int readlines(char *lineptr[], int maxlines);
unsigned getline2(char *s, int size);
void printlines(char **lineptr, int size, int numlines);

#endif // LINEHOLDER_H_INCLUDED

第一个源文件是:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lineholder.h"



int main(int argc, char *argv[])
{
  char *lineptr[MAXLEN];      /* input lines */
  int linecount = 0;
  int tail_count = 0;

   int i;

for (i = 1 ; i < argc ; ++i)
{
    char *arg = argv[i]; 
    if (strcmp(arg, "-n") == 0);
    {
        char *endptr;
        tail_count = strtol(arg, &endptr, 10);     
        if (*endptr == '\0')
            continue;
        fprintf(stderr, "warning , argument `%d' is not an integer\n", 1 + i);
     }
 }
  if (!tail_count)
    tail_count = 10;

  if ((linecount = readlines(lineptr,MAXLINES)) >= 0)
    printlines(lineptr, linecount,tail_count);

  return 0;
}

第二个源文件是:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lineholder.h"

unsigned getline2(char *s, int size);

int readlines(char *lineptr[], int maxlines)
{ 
  int len, nlines;
  char *p, line[MAXLEN];

  nlines = 0;

  while ((len = getline2(line, MAXLEN)) > 0) {
    p = malloc(len);
    if (nlines >= maxlines || p == NULL) {
      return -1;
    } else {
      // line[len-1] = '\n';
      if ((len > 0) && line[len-1] == '\n') line[len-1] = '\n';
      strcpy(p,line);
      lineptr[nlines++] = p;
    }
  }
  return nlines;
}

void printlines(char **lineptr, int size, int numlines)
{
  /* 72 lines, we start on line 62 */
  int print_start;
  int line;

  print_start = size - numlines;
  for (line=print_start; line < size; line++)
    printf("%s", lineptr[line]);
}

unsigned getline2(char *s, int size)
{
  int i, c;

  for (i=0; i<size-1 && (c=getchar()) != EOF && c != '\n'; ++i)
    *s++ = c;
  if (c == '\n') {
    *s++ = c;
    ++i;
  }
  *s = '\0';

  return i;
}

使用 makefile 构建它后,我将获得一个名为 tails 的可执行文件 当我运行 ./tails test.out 时,我收到分段错误核心转储错误。谁能帮我弄清楚我想在哪里分配我不应该分配的内存?

谢谢

感谢你们的帮助,我更新了代码,但我的问题仍然存在。

【问题讨论】:

  • 您可能存在内存泄漏。如果在readlines 函数中读取一行,分配内存,然后表达式nlines &gt;= maxlines 为真,该怎么办?
  • 0) int tail_count; 应该是 int tail_count=0;
  • 1) char *lineptr[MAXLEN]; , readlines(lineptr,MAXLINES) 大小不匹配。

标签: c


【解决方案1】:

您将指针递增两次,因为您在strcmp(*argv++, "-n") 中再次递增它,在第二种情况下,您可能在strtol(*argv, NULL, 10) 中读取超出范围。

while (*++argv) { /* First time you increment the pointer */
    if (strcmp(*argv++,"-n") == 0); /* You do it again */
        /* If *++argv was `NULL' you went after it anyway
         * so this is undefined behavior 
         */
        tail_count = strtol(*argv, NULL, 10);

这不是必须的

while (*++argv)

你可以使用 argc 来解决这个问题

int i;

for (i = 1 ; i < argc ; ++i)
 {
    char *arg = argv[i]; 
    if (strcmp(arg, "-n") == 0);
     {
        char *endptr;
        tail_count = strtol(arg, &endptr, 10);     
        if (*endptr == '\0')
            continue;
        fprintf(stderr, "warning , argument `%d' is not an integer\n", 1 + i);
     }
 }

main() 中的argc 参数包含传递给程序的命令行参数的数量,当然包括argv[0],这是程序本身的名称。

另外,接收lineptr 的函数的签名是错误的

void printlines(char **lineptr, int size, int numlines)

应该是

void printlines(char *lineptr[MAXLEN], int size, int numlines)

【讨论】:

  • 但是argv NULL 已终止。 argv[argc] 应始终为 NULL
  • @JoachimPileborg 总是?只有当你使用像execl() 这样的函数来执行程序时,这不是真的吗?那argc有什么意义呢?
  • 根据 5.1.2.2.1 的标准,“argv[argc] 应为空指针”。
  • @GreatDane 我正在阅读它,感谢您指出这一点。我一直依赖argc
  • 删除它确实修复了我收到的警告,但我仍然遇到分段错误
【解决方案2】:

当您的应用程序尝试访问它没有权限的内存时,就会出现分段错误。在这种情况下,操作系统将生成一个 SIGSEGV。这通常会终止您的应用程序并执行核心转储。

默认情况下,核心转储被关闭或严格限制以防止填满磁盘空间。

可以使用ulimit -c unlimted 轻松打开它们,这将允许创建无限大小的核心文件。核心文件通常在当前工作目录中创建。

如果您使用-g(调试符号)标志编译您的应用程序,您现在可以通过运行找出问题所在:

gdb

要获取调用堆栈,请在 gdb 中键入 bt 命令。

【讨论】:

    【解决方案3】:

    getline2() 读取最后一个'\n' 之后,下次调用它时可能会返回0,因为'\n' 是文件中的最后一个字符。

    while ((len = getline2(line, MAXLEN)) > 0) {
      p = malloc(len);
      if (... || p == NULL) {
    

    malloc(0) 可能不会返回 NULL,因此代码会继续尝试 line[-1] = '\n';,这是未定义的行为。

        ...
        line[len-1] = '\n';
    

    最后一行可能不会以'\n' 结尾,在这种情况下line[len-1] = '\n'; 会去掉一个有价值的`char。更好的防御性代码

        // line[len-1] = '\n';
        if ((len > 0) && line[len-1] == '\n') line[len-1] = '\n';
    

    【讨论】:

    • 好点。这并不能解决我的问题,因为我仍然收到错误消息,但感谢您指出该潜在问题。我更新了上面的代码以反映这一点
    猜你喜欢
    • 2018-07-28
    • 2021-06-03
    • 1970-01-01
    • 2023-04-04
    • 2022-01-14
    • 2017-02-25
    • 2016-07-12
    • 2018-03-16
    • 1970-01-01
    相关资源
    最近更新 更多