"malloc(sizeof(struct a*))"和"malloc(sizeof(struct a))"是否相同?

San*_*raj 5 c struct pointers

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

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

这里有一些关于memory使用malloc()wrt structures和.的分配的基本理解pointers

  • malloc(sizeof(struct a) * n)分配n类型struct a元素的数量.并且,可以使用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".并且,可以使用a来存储和访问分配的存储器位置pointer-to-(pointer-to-"struct a").基本上是一个struct a **.

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

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

data * array = NULL;

if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
    printf("unable to allocate memory \n");
    return -1; 
}   
Run Code Online (Sandbox Code Playgroud)

代码段如下:

#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 successful\n");

    for (i=0 ; i<n ; i++) {
        array[i].value1 = val++;
        array[i].value2 = val++;
    }   

    for (i=0 ; i<n ; i++) {
        printf("%3d %3d %3d\n", i, array[i].value1, array[i].value2);
    } 

    free(array);
    printf("freeing successful\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:好的,如果我错误地执行以下操作

data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
Run Code Online (Sandbox Code Playgroud)

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

SLa*_*aks 7

没有.

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

  • @SangeethSaravanaraj:未定义的行为并不意味着程序将始终崩溃,它只是意味着程序生成错误,您无法定义它的行为. (2认同)

Dan*_*her 5

似乎存在一个根本性的误解.

malloc(sizeof(struct a)*n)分配n个类型struct a元素.

不,这就是人们通常在这样的电话之后使用它的原因.malloc(size)分配一个size字节的内存区域.你对该地区的所作所为完全取决于你.唯一重要的是你不要超越分配内存的限制.假设4字节floatint8字节double,成功后malloc(100*sizeof(float));,您可以使用400字节中的前120个作为15 double秒的数组,接下来的120作为30 float秒的数组,然后在其char后面放置一个20 秒的数组int如果您愿意,可以用35 秒填充剩余的140个字节.这是完全无害的定义行为.

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

some_type **array = malloc(100 * sizeof(data *)); // intentionally unrelated types
Run Code Online (Sandbox Code Playgroud)

非常好,它可能不是你想要的记忆量.在这种情况下很可能是因为指针往往具有相同的大小,而不管它们指向的是什么.

更容易给你错误的内存量

data *array = malloc(n * sizeof(data*));
Run Code Online (Sandbox Code Playgroud)

就像你拥有它一样.如果使用分配的内存作为n类型元素的数组data,则有三种可能性

  1. sizeof(data) < sizeof(data*).那你唯一的问题是你在浪费一些空间.
  2. sizeof(data) == sizeof(data*).一切都很好,没有浪费空间,好像你根本没有打字错误.
  3. sizeof(data) > sizeof(data*).然后,您将访问在触摸稍后的数组元素时不应访问的内存,这是未定义的行为.根据各种各样的事情,可以始终如一地工作,好像你的代码是正确的,立即崩溃与segfault或其间的任何东西(从技术上讲,它可能以一种不能有意义地置于这两者之间的方式运行,但这将是不寻常的).

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

在你的例子中.data是4分.8个字节(可能),在64位系统上将它们放入1. resp.2.概率很高,在32位系统上分为2分.3.

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

type *pointer = malloc(num_elems * sizeof(*pointer));
Run Code Online (Sandbox Code Playgroud)