【问题标题】:How Much Stack Memory am I Using? <C>我使用了多少堆栈内存? <C>
【发布时间】:2018-05-02 13:59:49
【问题描述】:

我正在用 C 编写作业,上传系统告诉我我使用了太多堆栈内存。我需要找到问题的根源,因为我有点卡住了。

有什么方法可以分析堆栈内存使用情况,甚至查看哪些变量使用它以及它们使用了多少?

编辑:这是代码。它不完整(因为这是使用参数启动文件时的情况 2;情况 1 工作正常),所以我希望我没有留下任何我不使用的功能等。

这意味着凯撒密码有点扭曲。在输入时,我得到两个未知大小的字符串。第一个是密码,第二个是应该接近解码的消息(它可能缺少字母,它可能有额外的字母)。代码工作正常,输出一切正常,但如果我输入更长的字符串(比如每个 200 个字符),上传系统开始说我使用了太多堆栈。

f.e.有输入(截图在这里https://imgur.com/a/gxWlZ

NOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM
        abcRkfgchijklmnbCGqrstuvpxyzeABQDEFQGvIJKLMNOPRTUVWPZabcdefghijklnopdrPstuvwxorkCzABCEqFDpGHdJMNOPQcRSTUNVGYuZbMcTefghjklmnopqrstcvgwyzABCOiGHIPJKLMNOYPQRsTUWvYYZaQcdZpfgCfiXjekmnopqrptuvtwxyiABCDQFGHUEIJKLMQOPQRSTfVWXYZ

我显然使用了 185232B 的堆栈内存。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

const char* alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

char rotate(char, int);
void shift(const char *src, char * dst, int offset);
char * inputstr(size_t size);
int edit_distance(const char *str1, const char *str2, int len1, int len2);

int main(int argc, char * argv[])
{
    char * source = inputstr(10);
    char * example = inputstr(10);
    size_t len_source = strlen(source);
    size_t len_example = strlen(example);

    //char *closest = calloc(len_source+1,sizeof(char));
    char * destination = calloc(len_source + 1, sizeof(char));
    int min_match = len_source;
    int best_i = 0;
    for (int i = 0; i < 52;++i)
    {
        shift(source, destination, i);
        int match = edit_distance(destination, example, len_source, len_example);
        //printf("%2d: %s ~ %s > %d\n",i, destination, example, match);
        if (match < min_match) {
            min_match = match;
            best_i = i;
        }
    }
    shift(source, destination, best_i);
    printf("%s\n", destination);
    free(source);
    free(example);
    //free(closest);
    free(destination);
    return 0;

}

char rotate(char original, int offset)
{
    int index;
    char * rest;
    rest = strchr(alphabet, original);
    index = (int)(rest - alphabet);
    int distance = (index + offset) % 52;
    char new = *(alphabet + distance);
    return new;
}

void shift(const char *src, char * dst, int offset)
{
    int counter = 0;
    int len = strlen(src);
    for (int i = 0; i < len; ++i)
    {
        dst[i] = rotate(src[i], offset);
        counter++;
    }

}


char * inputstr(size_t size)
{
    char * str;
    if ((str = realloc(NULL, size * sizeof(char))) == NULL) {
        printf("Not enough memory\n");
        free(str);
        exit(69);
    }
    int ch;
    size_t len = 0;
    while ((ch = getchar()) != EOF && ch != '\n') {
        if (isalpha(ch)) {
            str[len] = ch;
            ++len;
            if (len == size) {
                size *= 5;
                if ((str = realloc(str, size * sizeof(char))) == NULL) {
                    printf("Not enough memory\n");
                    free(str);
                    exit(69);
                }
            }
        } else {
            fprintf(stderr, "Error: Chybny vstup!\n");
            free(str);
            exit(100);
        }
    }
    str[len++] = '\0';
    return str;
}

int edit_distance(const char *str1, const char *str2, int len1, int len2)
{
    int d[len1 + 1][len2 + 1];
    for (int i = 0; i <= len1; ++i)
    {
        d[i][0] = i;
    }
    for (int j = 0; j <= len2; ++j)
    {
        d[0][j] = j;
    }
    for (int j = 1; j <= len2; ++j)
    {
        for (int i = 1; i <= len1;
        ++i)
        {
            if (str1[i - 1] == str2[j - 1]) {
                d[i][j] = d[i - 1][j - 1];

            } else {
                int min = d[i - 1][j] + 1;
                if ((d[i][j - 1] + 1) < min) {
                    min = d[i][j - 1] + 1;
                }
                if ((d[i - 1][j - 1] + 1) < min) {
                    min = d[i - 1][j - 1] + 1;
                }
                d[i][j] = min;

            }
        }
    }
    //printf("%d %d\n", len1, len2);
    /*for(int i = 0; i<=len1; ++i)
    {
        for(int j = 0; j<=len2; ++j)
        {
            printf("%2d ", d[i][j]);
        }
        printf("\n");
    }*/
    return d[len1][len2];
}

【问题讨论】:

  • 您可能有一些太大的局部变量。显示您的代码。
  • 调试器应该能够帮助您解决这个问题。您是否偶然使用了任何递归函数?
  • 不使用任何递归。
  • 好了,我的代码已经上线了,你可以查一下。我一无所知。
  • 我两个月前才开始学习C,所以肯定有一些初学者的巨大错误。 f.e. void shift() 函数中的计数器。绝对没用,我忘记删除了。我怀疑这会有所作为。

标签: c memory stack


【解决方案1】:

罪魁祸首看起来像edit_distance中的这个数组:

int d[len1 + 1][len2 + 1];

这个数组的大小为(len_source + 1) * (len_example + 1) * sizeof(int)。因此,例如,如果源字符串和示例字符串各为 200 个字节,int 为 4 个字节,则该数组大约有 200 * 200 * 4 = 160000 个字节。这些不是很大的字符串,但已经超过了你的堆栈限制的 3 倍。

您可以动态分配一个二维数组(技术上是一个指针数组,每个指针指向一个整数数组),而不是在堆栈上声明这个数组:

int i;
int **d = malloc(sizeof(int *) * (len1 + 1));
for (i=0; i < len1 + 1; i++) {
    d[i] = malloc(sizeof(int) * (len2 + 1));
}

然后确保你保存了你想要返回的值并释放所有东西:

int result = d[len1][len2];
for (i=0; i < len1 + 1; i++) {
   free(d[i]);
}
free(d);
return result;

【讨论】:

  • 你能把我编辑的代码全部放上来吗?我无法完全理解我将如何实现这一点。
  • @Welsy 只需将edit_distance开头的数组声明替换为动态分配的指针,并在底部进行清理。
  • 如果性能很关键,请考虑使用malloca/freea
  • 伙计,它成功了。你是天才。截止日期前2小时16分钟,我因此熬夜了9个小时,非常感谢!谢谢谢谢谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-05-15
  • 2016-06-29
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 2016-09-19
  • 2011-07-16
  • 2015-05-01
相关资源
最近更新 更多