c语言 - "malloc(sizeof(struct a *))"和"malloc(sizeof(struct a))"是一样的吗?



这个问题是Malloc调用崩溃的延续,但在其他地方有效

我尝试了以下程序,发现它可以工作(即不会崩溃 - 上面提到的链接中也提到了这一点(。我可能很幸运能让它工作,但我正在寻找 SO 专家关于为什么它有效的合理解释?!

以下是使用malloc() w.r.t structurespointers分配memory的一些基本理解

  • malloc(sizeof(struct a) * n)分配n类型struct a元素的数量。并且,可以使用pointer-to-type-"struct a"存储和访问此内存位置。基本上是一个struct a *.
  • malloc(sizeof(struct a *) * n)分配n类型struct a *元素的数量。然后,每个元素都可以指向类型 struct a 的元素。基本上malloc(sizeof(struct a *) * n)分配了一个array(n-elements)-of-pointers-to-type-"struct a"。并且,可以使用pointer-to-(pointer-to-"struct a")存储和访问分配的内存位置。基本上是一个struct a **.

所以当我们创建一个array(n-elements)-of-pointers-to-type-"struct a"时,是不是

  1. 将其分配给struct a *而不是struct a **有效?
  2. 使用 pointer-to-"struct a" 访问/取消引用分配的array(n-elements)-of-pointers-to-type-"struct a"有效 ?

data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
    printf("unable to allocate memory n");
    return -1; 
}   

代码片段如下:

#include <stdio.h>
#include <stdlib.h>
int main(void) 
{
    typedef struct { 
        int value1;
        int value2;
    }data;
    int n = 1000;
    int i;
    int val=0;
    data * array = NULL;
    if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
        printf("unable to allocate memory n");
        return -1; 
    }   
    printf("allocation successfuln");
    for (i=0 ; i<n ; i++) {
        array[i].value1 = val++;
        array[i].value2 = val++;
    }   
    for (i=0 ; i<n ; i++) {
        printf("%3d %3d %3dn", i, array[i].value1, array[i].value2);
    } 
    free(array);
    printf("freeing successfuln");
    return 0;
}

编辑:好的说,如果我错误地做了以下操作

data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {

有没有办法捕获(在编译时使用任何GCC标志(这些意外的编程错别字,这些错别字有时可能起作用,并且可能随时爆发!我用-Wall编译了这个,没有发现任何警告!

似乎有一个根本性的误解。

malloc(sizeof(struct a( * n( 分配 n 个类型的结构 A 元素。

不,这只是人们通常在这样的电话之后使用它的方式。 malloc(size)分配一个 size 字节的内存区域。你对那个地区做什么完全取决于你。唯一重要的是不要超出分配内存的限制。假设 4 字节floatint 和 8 字节double,在成功malloc(100*sizeof(float));后,您可以将 400 字节中的前 120 个用作 15 double s 的数组,接下来的 120 个作为 30 float s 的数组,然后在后面放置一个 20 char s 的数组,如果您愿意,可以用 35 int s 填充剩余的 140 个字节。这是完全无害的定义行为。

malloc返回一个void*,它可以隐式转换为任何类型的指针,因此

some_type **array = malloc(100 * sizeof(data *)); // intentionally unrelated types

完全没问题,它可能只是不是您想要的内存量。在这种情况下,很可能是这样,因为无论指针指向什么,它们往往具有相同的大小。

更有可能给你错误的内存量是

data *array = malloc(n * sizeof(data*));

就像你一样。如果使用分配的内存块作为类型 datan 元素数组,则有三种可能性

  1. sizeof(data) < sizeof(data*) .那么你唯一的问题是你在浪费一些空间。
  2. sizeof(data) == sizeof(data*) .一切都很好,没有浪费空间,好像你根本没有错别字。
  3. sizeof(data) > sizeof(data*) .然后,您将访问在触摸后面的数组元素时不应该访问的内存,这是未定义的行为。根据各种因素,这可以始终如一地工作,就好像您的代码是正确的一样,立即崩溃并出现段错误或介于两者之间的任何内容(从技术上讲,它的行为方式可能无法有意义地放置在这两者之间,但这将是不寻常的(。

如果你故意这样做,知道第1点或第2点适用,这是不好的做法,但不是错误。如果你无意中这样做,无论哪一点适用,都是一个错误,无害但很难找到,而 1.或 2.适用,有害,但在 3 的情况下通常更容易检测。

在你的例子中。 data是 4 到 8 字节(可能(,在 64 位系统上将它们放入 1。第二部分。很有可能,在 32 位系统上变成 2 或 3。

避免此类错误的推荐方法是

type *pointer = malloc(num_elems * sizeof(*pointer));

No.

sizeof(struct a*)指针的大小。
sizeof(struct a)是整个结构的大小。

这个array = (data *)malloc(sizeof(data *) * n)分配了一个sizeof(data*)(指针(来构造data,如果你想这样做,你需要一个你的array成为一个data** array

在您的情况下,您希望指针指向sizeof(data),内存中的结构,而不是另一个指针。 这将需要一个data**(指针指向指针(。

将其

分配给结构 * 而不是结构 ** 是否有效?

好吧,从技术上讲,这样分配是有效的,但是取消引用这样的指针是错误的(UB(。你不想这样做。

使用指向"结构 A"的指针访问/取消引用分配的数组(n 元素(的指针到类型"结构 A"有效?

不,未定义的行为。

最新更新