C语言 程序终止时,我设置的结构数组的大小为89,但工程时,我设置为88

5lhxktic  于 2023-06-21  发布在  其他
关注(0)|答案(2)|浏览(107)

我正在做一个词汇训练项目,你可以在那里添加,练习,查看和改变你的词汇。对于每个英语单词(最多50个字符),我希望有一个瑞典语翻译/定义(最多999个字符)和一些例句(最多10个,每个包含最多999个字符)。为此,我使用了一个名为Word的结构,因为我需要多个单词,所以我制作了一个大小为100(最多100个单词)的Word类型的数组。这工作正常,直到我创建了一个函数,我想在其中声明一个新的Word类型的临时数组(因为我将随机化顺序,我不希望第一个数组受到影响)。我将大小设置为MAXSIZE(100),但随后整个程序终止。经过一些实验后,我发现当我将临时数组的大小设置为92时,程序可以工作,但如果我将其设置为93,则无法工作。这是为什么呢?这和我的数组占用太多内存有关吗?我对c编程很陌生,因此简单的解释会很好。代码如下:谢谢你。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXWORDS 92
#define MAXEWORD 50
#define MAXSENTENCE 999
#define MAXNR 10

typedef struct {
    char eWord[MAXEWORD];
    char sWord[MAXSENTENCE];
    char sentence[MAXNR][MAXSENTENCE];
} Word;

void printEnglishWords(Word theWords[], int thePos) {
    for(int i=0; i<thePos; i++) {
        printf("%s, ", theWords[i].eWord);
    }
}

void shuffleWords(Word theWords[], int thePos) {
    Word wordTemplate[MAXWORDS];
    Word hold;

    for(int i=0; i<thePos; i++) {
        wordTemplate[i]=theWords[i];
    }

    for(int i=0; i<thePos; i++) {
        int index=rand()%thePos;
        hold=wordTemplate[i];
        wordTemplate[i]=wordTemplate[index];
        wordTemplate[index]=hold;
    }

    printf("\n");
    printEnglishWords(wordTemplate, thePos);  

}

int main(void) {

    srand((unsigned) time(NULL));
    Word myWords[MAXWORDS];
    int pos;
    
    myWords[0]=(Word){"Dog", "Hund", {"I own a dog"}};
    myWords[1]=(Word){"Cat", "Katt", {"I do not own a cat"}};
    myWords[2]=(Word){"Food", "Mat", {"I am hungry and I need some food"}};
    pos=3;

    printEnglishWords(myWords, pos);    //output is Dog, Cat, Food, 

    shuffleWords(myWords, pos);         //output is Food, Dog, Cat, 

   return 0;

}

当MAXWORDS为92时,输出写在上面。但是,当MAXWORDS为93时,只写入“Dog,Cat,Food”,shuffleWords函数不起作用。

wi3ka0sx

wi3ka0sx1#

结构Word的尺寸至少为

MAXEWORD + MAXSENTENCE + MAXNR * MAXSENTENCE

其为11039字节。myWords[MAXWORDS]则为920129字节,并被示例化为局部变量,在正常的C执行环境中,它将在堆栈上示例化。堆栈大小取决于执行环境、操作系统或构建时提供的链接器选项,但它是有限的,在您的情况下可能太小。这将是一个“堆栈溢出”后,该网站被命名。
在这种情况下,你可以简单地声明它static

static Word myWords[MAXWORDS];

在生命周期和可见性方面,当在main()中声明时,static和非静态之间几乎没有区别,但在其他情况下,它可能不是适用的解决方案,因为如果static的语义。
shuffleWords()又增加了1026627个字节,我怀疑这是堆栈溢出的时候。在这种情况下,也可以是static
您需要了解C中一般有三种内存分配:

  • 堆栈-局部变量、函数参数和返回值的临时用途。函数返回时自动释放
  • 静态-在构建时由链接器分配,在程序启动时创建和初始化,并在程序终止时释放。
  • 动态-由您的代码从系统堆“按需”创建和释放。

然而,在这两种情况下,静态分配虽然简单,但却是浪费的。在本例中,您分配了92个元素,但只使用了3个。这就是动态分配可能有用的地方,当需求在运行时才知道时,只分配您需要的东西。

i7uaboj4

i7uaboj42#

没有更多的信息很难说,但是如果我数得正确,你的数组在这里接近1MB。这是一次要分配的大量内存。这个“可能”就是问题所在。但是像这样的东西是非常依赖于体系结构和系统的。
C缺少了许多易于使用的功能,例如Java提供的功能。如果你不告诉C在heap上分配内存,它就不会这样做。
尝试将数组放在堆上。导入stdlib.h并为阵列分配专用内存。
而不是:

Word myWords[MAXWORDS];

它看起来像这样:

Word *myWords;

myWords = malloc(MAXWORDS * sizeof(Word));

您还可以将shuffleWords()函数更改为:

void shuffleWords(Word *theWords, int thePos) {
    ...

}

现在wordtemplate是指向堆内存的指针。wordtemplate[0]将获得第一个元素,wordtemplate[0].eWord[0]将获得结构中的数组。你也可以使用指针数组和循环来分别为每个结构分配内存。
有很多很好的来源,告诉你如何malloc,如果你谷歌它。或者right here on stackoverflow。当您不再需要free内存时,最好也使用它。我认为你的情况没有必要。但我强烈建议你熟悉所有这些,如果你想用C编程更多的东西。
编辑:要分割已分配的内存,您可以尝试以下操作。

Word *myWords[MAXWORDS];
for(i = 0; i < MAXWORDS; i++)
  myWords[i] = malloc(sizeof(Word));

这将改变您访问阵列的方式。您甚至可以将指针数组放在堆中。但我想你可能想简单点。

相关问题