超出C内存限制

时间:2018-02-27 10:31:18

标签: c

我目前是C学生的导师。在他的课程中,大学安装了一台运行Mooshak的服务器(一种能够接收代码并对其进行测试的软件)。

我们开发了一个代码,编译并在发送到服务器之前在本地进行了测试,一切都很顺利。但是,当我们尝试将其发送到服务器时,服务器声明"超出内存限制"。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <string.h>

#define LIMITE_CARACTERES 1000
#define LIMITE_GENES 100000

char genes[LIMITE_GENES][LIMITE_CARACTERES];

char* copiar_por_espaco(char* string, char* dest)
{
    for(int i = 0; i < strlen(string); i++)
    {
        if(' ' == string[i])
        {
            strncpy(dest, string, i);
            dest[i] ='\0';
            if( i + 1 >= strlen(string))
                return NULL;
            else
                return &string[i+1];
        }
    }
    if(strlen(string) == 0)
    {
        return NULL;
    }
    else
    {
        strcpy(dest, string);
        return NULL;        
    }
}


void genes_f()
{
    char s[LIMITE_CARACTERES];
    int numero_genes = 0;
    while(scanf("%s", s) != EOF)
    {
        char *auxiliar = s;
        while(auxiliar != NULL && strlen(auxiliar) != 0)
        {
            auxiliar = copiar_por_espaco(auxiliar, genes[numero_genes]);
            numero_genes++;
        }
    }
    if(numero_genes <= 20)
    {
        for(int i = 0; i < numero_genes; i++)
        {
            printf("%s\n", genes[i]);
        }
    }
    else
    {
        for(int i = 0; i < 10; i++)
        {
            printf("%s\n", genes[i]);
        }

        for(int i = numero_genes - 10; i < numero_genes;i++)
        {
            printf("%s\n", genes[i]);
        }
    }
}


int main()
{
    genes_f();
    return 0;
}

请注意,值LIMITE_CARACTERES和LIMITE_GENES是一项分配要求(尚未告知有关内存分配的信息)。上面的代码给出了超过内存限制&#34;但如果我将第一个分成两行,服务器不会抛出该错误并接受我们的解决方案:

char* copiar_por_espaco(char* string, char* dest)
{
    int len = strlen(string); //This line was taken out from the for
    for(int i = 0; i < len; i++) //Now we used the variable instead
    {
        if(' ' == string[i])
        {
            strncpy(dest, string, i);
            dest[i] ='\0';
            if( i + 1 >= strlen(string))
                return NULL;
            else
                return &string[i+1];
        }
    }
    if(strlen(string) == 0)
    {
        return NULL;
    }
    else
    {
        strcpy(dest, string);
        return NULL;
    }
}

我不知道为什么。有人对此有解释吗?

编辑:在工作函数中添加注释,以便轻松发现唯一的更改。

编辑2:输入将有几行带有单词(应跳过空白行),用空格分隔。该计划应该分开并采用每个词:

输入

A BDD TES QURJ

test dog cat heart

cow
bird tree

输出

A
BDD
TES
QURJ
test
dog
cat
heart
cow
bird
tree

2 个答案:

答案 0 :(得分:2)

您忘记在数组中包含空终止符的额外字节。如果LIMITE_CARACTERES是作为输入提供的字符串的最大长度,那么您需要一个大小为LIMITE_CARACTERES + 1的数组来存储它。所以你需要改变这一行

char genes[LIMITE_GENES][LIMITE_CARACTERES];

char genes[LIMITE_GENES][LIMITE_CARACTERES + 1];

答案 1 :(得分:1)

由于您是导师,我会提供反馈,以便您可以正确地教导您的学生(因此这不是您问题的答案)。

<强> copiar_por_espaco

for(int i = 0; i < strlen(string); i++)

对循环中没有变化的变量重复调用strlen是浪费CPU周期。实际上,您应该在循环之前计算长度并在循环中使用它。这也适用于if( i + 1 >= strlen(string))

if(' ' == string[i])...

请注意,保证字符串不包含空格,因为它是使用scanf读取的。因此,该函数将始终返回NULL

if(strlen(string) == 0) return NULL;

你在循环之后测试它,但逻辑规定你在任何处理之前执行此操作并且可以缩短为if (!*string) return NULL;这也会使代码更加美观,因为不需要else部分(它不管怎样都不需要。)

<强> genes_f

while(scanf("%s", s) != EOF)

scanf-guru可能在这里有所帮助,但我相信格式说明符中必须有一个空格,因此它将跳过前导空格" %s"。我相信你的方式只会读取一个字符串,然后在每次scanf调用时无限循环返回零。您应该测试scanf的结果,以获取格式说明符成功转换的数量,而不是EOF。因此,请检查1

if(numero_genes <= 20)

你的印刷很有趣。这一切都可以作为一个循环:

    for(int i = numero_genes; i < numero_genes; i++)
        printf("%s\n", genes[i]);

你必须对你的基因数进行边界检查:

numero_genes<LIMITE_GENES