【问题标题】:Malloc affecting random integer valueMalloc 影响随机整数值
【发布时间】:2014-05-08 20:10:50
【问题描述】:

我正在用 C 语言编写一个虚拟内存模拟器,在 linux 上编译,我得到了一些相当奇怪的东西。它接受一个文件 IO,我将它放入一个 int* plist 中。

我打印了这个“plist”数组,结果是 0 100 1 200 2 400 3 300 等等

问题是它似乎 malloc 或某些东西正在随机将 plist[3] 更改为 0。看起来不应该那样,但我在每一行代码中都放置了一个 print 语句来打印 plist [3],和

tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));

是它改变的地方。 plist[3] = 行前 300,行后 0。它只在 i = 2 时才这样做。循环的前 3 轮运行良好,在第 3 轮,它改变了第 4 轮的值。我不知道为什么,malloc 会改变一个值没有什么意义一个完全不相关的数组 - 我是否可能已经超出了一些空间限制,即使我基本上将堆用于所有内容?如果我这样做了,它只会改变随机数组中的值吗?

for(i = 0; i < 4; i++){

    num_pages = plist[i] / P1;

    tables[i].page_num = (char**) xmalloc(num_pages * sizeof(char*));

    tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));


    //initialize page numbers and valid bits
    for(j = 0; j < 10; j++){
        tables[i].page_num[j] = (char*) xmalloc(16*sizeof(char));
        tmp = itoa(i, tmp);
        strcat(tables[i].page_num[j], tmp);
        strcat(tables[i].page_num[j], "p");
        tmp = itoa(j, tmp);
        strcat(tables[i].page_num[j], tmp);

        tables[i].valid[j] = 0;
    }
}

这是表的结构:

typedef struct s_page_table
{
    char** page_num;
    char* valid;
} t_page_table;

这就是 xmalloc(它只是一个让事情变得更简单的包装器):

void* xmalloc(int s)
{
    void* p;
    p = malloc(s);
    if (p == NULL)
    {
        printf("Virtual Memory Exhausted");
        exit(1);
    }
    return p;
}

编辑:如果我取出引用表[i].valid 的两行,则问题不存在。 plist[3] 保持不变。 num_pages 总是 >= 10。我将 j 设置为 0 到 10 只是为了减少输出以进行调试。

编辑 2:如果我将 valid 从 char* 更改为 int* 它不起作用。如果我将其更改为 int,则可以。

【问题讨论】:

  • 我们是否应该猜测tmp 是什么,它来自哪里,以及为什么它在itoa 中被使用,而代码中没有其他地方出现?
  • num_pages 是否小于 10? IE。 j 循环不应该使用num_pages 作为绑定而不是10
  • 我试图猜测P1 可能是什么。 @user3475234 如果你发布一个完整的可编译程序,人们解决这些谜题会容易得多。
  • 检查您的所有strcats 是否不会溢出您分配的内存量。我会考虑用snprintf(tables[i].page_num[j], 16, "%dp%d", i, j); 替换整个块
  • 还要检查num_pages &gt;= 10

标签: c arrays memory malloc


【解决方案1】:

有几种可能性,包括(但不限于):

  • tables[i] 越界;
  • plist 包含一个悬空指针(即它已被释放);
  • plist 尚未初始化;
  • plist 没有你想象的那么大,即plist[3] 超出范围。

如果您无法通过查看代码找出问题所在,valgrind 是您的朋友。

【讨论】:

  • +1,但不确定第一个项目符号。如果tables 的条目少于4 个或plist[i] &lt; 10*P1,那不是tables[i].page_num[j]tables[i].valid[j] 超出范围吗? P1 的值不影响tables[i] 是否越界。
  • @pat:你说的很对,谢谢。我混淆了ij 索引。我已经编辑了答案。
  • 好的,我经历了这些,我认为这些不是问题。 i 上升到 10 - 我只是将它设置为 4,这样我就可以弄清楚 plist[3] 有什么问题。我还没有开始释放任何东西(因为它仍在进行中,我想测试我到目前为止所拥有的东西)。 plist 已初始化,有十个点,我打印它 - 它从文件输入中读取,我在此之前循环打印输出,结果是正确的。问题是 plist[3] 是整个循环的 300,直到 i = 2 并且它分配 tables[i].valid - 如果我删除分配,它会起作用。
  • @user3475234:如果您仔细浏览了该程序,但仍然找不到内存错误的位置,我鼓励您尝试valgrind。它是免费的,可能很快就能解开谜团!
【解决方案2】:

好的。所以我相信问题出在在初始化所有内容之前使用字符串。我不完全确定原因,也许其他人可以详细说明,但是当我将初始化封装在它自己的函数中,比如只做mallocs,然后分别创建字符串,plist变量不受影响。

对于那些感兴趣的人,封装的函数看起来像这样:

t_page_table* table_builder(int* p, int x, int num_tables)
{
    t_page_table* ret = xmalloc(num_tables * sizeof(*ret));
    int i, tmp, j;
    for(i = 0; i < num_tables; i++){
        tmp = (p[i]/x); 
        ret[i].page_num = xmalloc(tmp * sizeof(char*));
        ret[i].valid = xmalloc(tmp * sizeof(char));
        for(j = 0; j < tmp; j++){
            ret[i].page_num[j] = xmalloc(16 * sizeof(char));
            ret[i].valid = 0;
        }
    }
    return ret;
}

【讨论】:

    猜你喜欢
    • 2013-04-21
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    • 2013-01-14
    • 2021-09-10
    • 1970-01-01
    相关资源
    最近更新 更多