我知道之前已经问过这个问题,我认为我理解有一个分段错误意味着我的某个地方有一个坏指针。话虽如此,我真的很感激帮助试图弄清楚我的错误在哪里。我有一个头文件和两个源文件
部首:
#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时,我收到了分段错误核心转储错误。任何人都可以帮我弄清楚我在哪里尝试分配我不应该的内存?
感谢
由于你们的帮助,我更新了代码,但我的问题仍然存在。
答案 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';