分段故障核心转储问题与C

时间:2015-04-20 13:36:38

标签: c

我知道之前已经问过这个问题,我认为我理解有一个分段错误意味着我的某个地方有一个坏指针。话虽如此,我真的很感激帮助试图弄清楚我的错误在哪里。我有一个头文件和两个源文件

部首:

#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时,我收到了分段错误核心转储错误。任何人都可以帮我弄清楚我在哪里尝试分配我不应该的内存?

感谢

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

3 个答案:

答案 0 :(得分:2)

您正在将指针递增两次,因为您在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);
     }
 }

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

此外,收到lineptr的函数的签名是错误的

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

应该是

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

答案 1 :(得分:2)

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

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

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

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

gdb

要获取callstack,请在gdb中键入bt命令。

答案 2 :(得分:1)

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

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';