【问题标题】:Dynamically allocating 2d array in c error在c错误中动态分配二维数组
【发布时间】:2019-03-06 18:37:22
【问题描述】:

我的问题很简单,我想为 c 中的二维数组分配内存,用 -1 填充它,然后释放它并退出程序。我的代码不断崩溃,我不知道我做错了什么...... 这就是我得到的:

int main(){

    int i,j;
    char str1[]="xxxabxcxxxaabbcc";
    char str2[]="abc";
    int len1=strlen(str1);
    int len2=strlen(str2);

    printf("%d %d",len1,len2);

    //allocate 2d_array

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

    //fill and print 2d array

    for(i=0;i<len1+1;i++){
        for(j=0;j<len2+1;j++){
            printf("i:%d j:%d",i,j);
            H_table[i][j]=-1;
            printf(" value:%d\n",H_table[i][j]);
        }
    }

    // free 2d array

    for(i=0;i<len1;i++){
        free(H_table[i]);
    }
    free(H_table);
    return 0;
}

所以发生的情况是,如果你将它们垂直放置,我想分配一个比 2 个字符串多 1 行和 1 列的数组。

这是我所期望的(括号中的东西显然不是表格的一部分,我把它放在那里进行比较):

   (x x x a b x c x x x a a b b c c)  
  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
a)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
b)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
c)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  

问题是代码在填满表格时会崩溃,对于那些特定的字符串,它总是在 i=9 和 j=3 时崩溃。奇怪的是,如果您交换 2 个字符串(在 str1 中放入“abc”),则代码会通过填充阶段,并在尝试释放数组时崩溃。

对于任何语法错误或stackoverflow错误,我很抱歉:P

欢迎任何想法 :) 提前谢谢

【问题讨论】:

  • 这里有一个提示:写 malloc 的最佳方式是:SomeType* some_variable = malloc(n * sizeof *some_variable);。例如:int** H_table = malloc((len1+1) * sizeof *H_table);H_table[i] = malloc((len2 + 1) * sizeof * H_table[i]);。在 C 语言中,没有必要明确区分 malloc 的返回值。使用sizeof *variable 而不是sizeof(whatever you think the type should be) 可以让您不必考虑类型应该是什么:-) 如果您以后将变量的类型从int* 更改为@,则不必更改987654329@
  • @rici 和 Mike Hatzak,这些错误是一种拼写错误,这个问题对其他人有用并且需要保留,还是删除它更好?
  • @rici 如果你想我删除我的答案,你把你的 ? ^^ 当我回答时,我看到 xing 平行地做了他的第一句话
  • @rici 好的,我删除它
  • 非常感谢大家的回答,看起来这个问题确实是一个错字,但是 xing 建议的事情确实使它工作(int->int*)。所以是的,正如 rici 所说,我将代码中的所有内容都更改为他所说的内容,只是为了确定。如果你想删除我不介意的线程,但它可以节省人们一些时间和挫败感,因为这些错误会让没有经验的人撞到墙上:P 再次感谢

标签: c arrays pointers malloc


【解决方案1】:

正如许多人指出的那样,您正在为H_table 分配空间len1 + 1整数,但它实际上应该是len1 + 1 指针的数组 (整数)。由于指针大于整数(无论如何,在您的系统上),您最终会因缓冲区溢出而导致未定义的行为。

这里有一个提示。通过始终对malloc 使用以下模型来避免此问题以及各种其他类似问题:

some_variable = malloc(n * sizeof *some_variable);

例如:

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

也就是说,让编译器找出变量(或左值)的正确类型。编译器比您更不容易出现拼写错误,并且不显式编写类型将使您以后更容易确定H_table 应该是longshortunsigned

出于同样的原因,不要显式转换malloc 的返回值。 C 自动将void* 转换为目标类型,如果您手动转换为错误类型,则不会提供错误。所以就让编译器来做吧;它打字更少、更安全、更面向未来。

请注意,如果您使用带有 sizeof 的表达式,编译器不会评估表达式 [注 1]。它只是找出类型并将其替换为表达式。所以不用担心额外的评估:没有。这也是为什么可以将此模型与声明一起使用的原因,即使在执行 mallocsome_variable 还没有值。


注意事项:

  1. 在一种情况下,编译器可能会在sizeof ex 中计算ex:如果ex 是一个可变长度数组。但是,在这种情况下,ex 始终是一个指针,因此这种情况不适用。

【讨论】:

    【解决方案2】:

    正如@xing 在他的评论中提到的,H_table 是一个指向整数的指针。所以你需要在第一个malloc 中将int 更改为int*。 这里:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main(){
    
        int i,j;
        char str1[]="xxxabxcxxxaabbcc";
        char str2[]="abc";
        int len1=strlen(str1);
        int len2=strlen(str2);
    
        printf("%d %d",len1,len2);
    
        //allocate 2d_array
    
        int **H_table = (int**)malloc((len1+1)*sizeof(int*));
        for (i=0; i<len1+1; i++){
            H_table[i] = (int*)malloc((len2+1)*sizeof(int));
        }
    
        //fill and print 2d array
    
        for(i=0;i<len1+1;i++){
            for(j=0;j<len2+1;j++){
                printf("i:%d j:%d",i,j);
                H_table[i][j]=-1;
                printf(" value:%d\n",H_table[i][j]);
            }
        }
    
        // free 2d array
    
        for(i=0;i<len1;i++){
            free(H_table[i]);
        }
        free(H_table);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-11-14
      • 2021-02-03
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 2015-09-17
      • 1970-01-01
      • 1970-01-01
      • 2021-01-26
      相关资源
      最近更新 更多