【问题标题】:Why does this c program crashe?为什么这个 c 程序会崩溃?
【发布时间】:2013-09-29 02:23:33
【问题描述】:

我想制作一个列表,例如10 通过键盘输入的句子。为了得到一条线,我使用了一个函数getline()。谁能解释为什么这个程序在进入第二行时会崩溃?哪里错了?

#define LISTMAX 100
#define LINEMAX 100
#include <stdio.h>
#include <string.h>
void getline(char *);
int main ()
{
    char w[LINEMAX], *list[LISTMAX];
    int i;
    for(i = 0; i < 10; i++)
    {
        getline(w);
        strcpy(list[i], w);
    }
    for(i = 0; i < 10; i++)
        printf("%s\n", list[i]);
    return 0;
}

void getline(char *word)
{
    while((*word++ = getchar()) != '\n');
    *word = '\0';
}

【问题讨论】:

  • 因为strcpy(list[i], w); 正在将数据复制到不确定的目标地址。您永远不会为副本的目标分配内存。 list[] 充满了不确定的地址值,因此我们进入了未定义的行为
  • 你可能想看看strndup()
  • 您可能还想考虑将一个上限传递给您的getline(),或者使用全局LINEMAX 和一个计数器。正如所写,只要您输入 100 个字符或更长的字符串(包括换行符),它就会触发未定义的行为。
  • @cdhowie: strndup() 不是标准的,所以 OP 的里程可能会有所不同。
  • @AndyG 取决于您对“标准”的定义。它是 POSIX 2008 的一部分。

标签: c arrays string function pointers


【解决方案1】:

字符串是一个内存块(一个数组),它包含chars,以'\0' 终止。 char *不是字符串;它只是一个指向字符串中第一个char 的指针。

strcpy 确实创建一个新字符串。它只是将数据从一个内存块复制到另一个内存块。所以你的问题是:你没有分配一块内存来保存字符串。

我将向您展示两种解决方案。第一个解决方案是:更改list的声明,使内存已经分配。如果你这样做,你可以避免使用strcpy,所以你的代码更简单:

// no need for w
char list[10][LISTMAX];

// ...

// get the line straight into list
// no need to copy strings
getline(list[i]);

但是,如果您想伸展自己,第二种解决方案是在您知道需要时分配内存块。你需要在 C 中做很多事情,所以现在也许是学习这项技术的好时机:

#include <stdlib.h> // include the malloc function

// ...

char w[LINEMAX], * list[LISTMAX]

// put this line between the getline and strcpy lines
list[i] = (char *) malloc((strlen(w) + 1) * sizeof(char));

此解决方案更复杂,但您只需为字符串分配所需的内存。如果字符串长度为 10 个字符,则您只需向系统请求足够的内存来保存 11 个字符(10 个字符 + '\0')。如果您想读入一个文件,但又不知道该文件有多大,这一点很重要。

顺便问一下,为什么将LINEMAXLISTMAX 作为单独的常量?你能想出它们可能不同的原因吗?为什么不将10 设为常量?这不是更好吗?

#define LINEMAX 100
#define NUMBER_OF_LINES 10

// ...

char list[NUMBER_OF_LINES][LINEMAX];

// ...

for (i = 0; i < NUMBER_OF_LINES; i++)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 2023-03-11
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多