c语言 - K&R 5.11 指向函数的指针 - 排序程序在第一行输入后崩溃



我在书中关于指针和内存管理的这一部分遇到了一些问题。

我的程序在第一行输入后崩溃了,我不知道问题出在哪里。

我试着写并执行了书中显示的代码-应该在第120页,关于函数指针的部分。基本上,我给出一些输入行,它们被排序,要么是数字排序(如果我用-n指定的话),要么是字典排序。我对函数的指针及其工作方式的理解没有问题(可能有一点),但是在我的第一行输入之后发生了一些意想不到的崩溃。基本上,当我执行代码并键入某些内容时,它会停止一会儿,然后终止。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN      1000
#define MAXLINES    5000
char *lineptr[MAXLINES];
int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
void myqsort(void *lineptr[], int left, int right,
int (*comp)(void *, void *));
int numcmp(char *, char *);
/* sort input lines */
int main(int argc, char *argv[])
{
int nlines;         /* number of input lines read */
int numeric = 0;    /* 1 if numeric sort */
if (argc > 1 && !strcmp(argv[1], "-n"))
numeric = 1;
if ((nlines = readlines(lineptr, MAXLINES)) > 0)
{
if (numeric)
myqsort((void **) lineptr, 0, nlines - 1,
(int (*)(void *, void *))(numcmp));
else
myqsort((void **) lineptr, 0, nlines - 1,
(int (*)(void *, void *))(strcmp));
writelines(lineptr, nlines);
return 0;
}
else {
printf("input too big to sortn");
return 1;
}
}
/* get the input line */
int getline(char *line, int max)
{
int c, i;
for (i = 0; i < max - 1 && (c = getchar()) != EOF && c != 'n'; i++)
line[i] = c;
if (c == 'n')
line[i++] = 'n';
line[i] = '';
return i;
}
/* swap: interchange v[i] and v[j] */
void swap(void *v[], int i, int j)
{
void *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
/* readlines: read input lines */
int readlines(char *lineptr[], int maxlines)
{
int len, nlines;
char *p, line[MAXLEN];
int getline(char *line, int max);
nlines = 0;
while ((len = getline(line, MAXLEN)) > 0)
{
p = (char*) calloc(len, sizeof(char*));
if ((nlines >= maxlines) || (p == NULL))
return -1;
if (strcmp(lineptr[nlines], "quit") == 0) {
free(p);
return 0;
}
line[len - 1] = '';   /* delete newline */
strncpy(p, line, len);
/* printf("%sn", p); used for debugging */
strncpy(lineptr[nlines++], p, len);

free(p);
}
return nlines;
}
/* writelines: write output lines */
void writelines(char *lineptr[], int nlines)
{
int i;
for (i = 0; i < nlines; i++)
printf("%sn", lineptr[i]);
}
/* myqsort: sort v[left]...v[right] into increasing order */
void myqsort(void *v[], int left, int right,
int (*comp)(void *, void *))
{
int i, last;
void swap(void *v[], int i, int j);
/* return if there are less than 2 elements */
if (left >= right)
return;
swap(v, left, (left + right) / 2);
last = left;
for (i = left + 1; i <= right; i++) {
if ((*comp)(v[i], v[left]) < 0)
swap(v, ++last, i);
}
swap(v, left, last);
myqsort(v, left, last - 1, comp);
myqsort(v, last + 1, right, comp);
}
/* numcmp: compare s1 and s2 numerically */
int numcmp(char *s1, char *s2)
{
double v1, v2;
v1 = strtod(s1, NULL);
v2 = strtod(s2, NULL);
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
}

我认为问题存在于readlines函数周围,这可能是内存管理的问题,但我根本不理解它。已经好几天了,这仍然让我挣扎,请帮帮我。提前谢谢你。

编辑:我试着运行gdb,这是发生的事情:

Reading symbols from sort.exe...
(gdb) r
Starting program: ...sort.exe
[New Thread 3444.0x4f8c]
test
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00007ffde739c160 in ucrtbase!strcmp () from C:WINDOWSSystem32ucrtbase.dll
(gdb) backtrace
#0  0x00007ffde739c160 in ucrtbase!strcmp () from C:WINDOWSSystem32ucrtbase.dll
#1  0x00007ff631a11a4f in readlines ()
#2  0x00007ff631a1182a in main ()
(gdb)

未初始化变量:

readlines函数中:

while ((len = getline(line, MAXLEN)) > 0)
{
p = (char*) calloc(len, sizeof(char*));
if ((nlines >= maxlines) || (p == NULL))
return -1;
if (strcmp(lineptr[nlines], "quit") == 0) {
free(p);
return 0;
}

lineptr未初始化使用。它可能指向内存中的任何东西,因此它的内容是不确定的,你的代码调用未定义行为。

原来的K&R代码首先将line的内容复制到calloc返回的指针(或他们写的内存分配器)中,然后在每次迭代时将其地址分配给lineptr的第i元素。

转换或不转换:

内存分配函数返回一个泛型void指针,或者自动提升为正确类型的void *。不需要强制转换malloc和family的结果。

void指针可以与任何其他类型的指针进行转换显式强制转换(C11 6.3.2.3和6.5.16.1)。

相关内容

  • 没有找到相关文章