简体   繁体   English

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

[英]Are “malloc(sizeof(struct a *))” and “malloc(sizeof(struct a))” the same?

This question is a continuation of Malloc call crashing, but works elsewhere 这个问题是Malloc调用崩溃的延续,但在其他地方有效

I tried the following program and I found it working (ie not crashing - and this was mentioned in the above mentioned link too). 我尝试了以下程序,我发现它工作(即没有崩溃 - 这也在上面提到的链接中提到)。 I May be lucky to have it working but I'm looking for a reasonable explanation from the SO experts on why this is working?! 我很幸运能让它工作但是我正在寻找SO专家对于它为什么有效的合理解释?!

Here are some basic understanding on allocation of memory using malloc() wrt structures and pointers 以下是使用malloc() wrt structurespointers分配memory一些基本知识

  • malloc(sizeof(struct a) * n) allocates n number of type struct a elements. malloc(sizeof(struct a) * n)分配n个类型struct a元素。 And, this memory location can be stored and accessed using a pointer-to-type-"struct a" . 并且,可以使用pointer-to-type-"struct a"pointer-to-type-"struct a"来存储和访问该存储器位置。 Basically a struct a * . 基本上是一个struct a *
  • malloc(sizeof(struct a *) * n) allocates n number of type struct a * elements. malloc(sizeof(struct a *) * n)分配n个类型struct a *元素。 Each element can then point to elements of type struct a . 然后,每个元素都可以指向struct a类型的元素。 Basically malloc(sizeof(struct a *) * n) allocates an array(n-elements)-of-pointers-to-type-"struct a" . 基本上malloc(sizeof(struct a *) * n)分配一个array(n-elements)-of-pointers-to-type-"struct a" And, the allocated memory location can be stored and accessed using a pointer-to-(pointer-to-"struct a") . 并且,可以使用pointer-to-(pointer-to-"struct a")来存储和访问所分配的存储器位置。 Basically a struct a ** . 基本上是一个struct a **

So when we create an array(n-elements)-of-pointers-to-type-"struct a" , is it 所以当我们创建一个array(n-elements)-of-pointers-to-type-"struct a" ,就是这样

  1. valid to assign that to struct a * instead of struct a ** ? 有效将其分配给struct a *而不是struct a **
  2. valid to access/de-reference the allocated array(n-elements)-of-pointers-to-type-"struct a" using pointer-to-"struct a" ? 有效访问/取消引用已分配的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; 
}   

The code snippet is as follows: 代码段如下:

#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;
}

EDIT: OK say if I do the following by mistake 编辑:好的,如果我错误地执行了以下操作

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

Is there a way to capture (during compile-time using any GCC flags) these kind of unintended programming typo's which could work at times and might blow out anytime! 有没有办法捕获(在使用任何GCC标志的编译时)这些无意识的编程错字,它可能有时会工作,并可能随时爆发! I compiled this using -Wall and found no warnings! 我用-Wall编译了这个,发现没有警告!

No. 没有。

sizeof(struct a*) is the size of a pointer . sizeof(struct a*)指针的大小。
sizeof(struct a) is the size of the entire struct. sizeof(struct a)是整个struct的大小。

There seems to be a fundamental misunderstanding. 似乎存在一个根本性的误解。

malloc(sizeof(struct a) * n) allocates n number of type struct a elements. malloc(sizeof(struct a)* n)分配n个类型struct a元素。

No, that's just what one usually does use it as after such a call. 不,这就是人们通常在这样的电话之后使用它的原因。 malloc(size) allocates a memory region of size bytes. malloc(size)分配size bytes的内存区域。 What you do with that region is entirely up to you. 你对该地区的所作所为完全取决于你。 The only thing that matters is that you don't overstep the limits of the allocated memory. 唯一重要的是你不要超越分配内存的限制。 Assuming 4 byte float and int and 8 byte double , after a successful malloc(100*sizeof(float)); 假设4个字节的floatint以及8个字节的double ,在成功的malloc(100*sizeof(float)); , you can use the first 120 of the 400 bytes as an array of 15 double s, the next 120 as an array of 30 float s, then place an array of 20 char s right behind that and fill up the remaining 140 bytes with 35 int s if you wish. ,您可以使用400字节中的前120个作为15个double s的数组,接下来的120作为30个float的数组,然后在其后面放置一个20个char的数组,并用35填充剩余的140个字节int如果你想秒。 That's perfectly harmless defined behaviour. 这是完全无害的定义行为。

malloc returns a void* , which can be implicitly cast to a pointer of any type, so malloc返回一个void* ,它可以隐式地转换为任何类型的指针,所以

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

is perfectly fine, it might just not be the amount of memory you wanted. 非常好,它可能不是你想要的记忆量。 In this case it very likely is, because pointers tend to have the same size regardless of what they're pointing to. 在这种情况下很可能是因为指针往往具有相同的大小,而不管它们指向的是什么。

More likely to give you the wrong amount of memory is 更容易给你错误的内存量

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

as you had it. 就像你拥有它一样。 If you use the allocated piece of memory as an array of n elements of type data , there are three possibilities 如果将分配的内存块用作n data类型元素的数组,则有三种可能性

  1. sizeof(data) < sizeof(data*) . sizeof(data) < sizeof(data*) Then your only problem is that you're wasting some space. 那你唯一的问题是你在浪费一些空间。
  2. sizeof(data) == sizeof(data*) . sizeof(data) == sizeof(data*) Everything's fine, no space wasted, as if you had no typo at all. 一切都很好,没有浪费空间,好像你根本没有打字错误。
  3. sizeof(data) > sizeof(data*) . sizeof(data) > sizeof(data*) Then you'll access memory you shouldn't have accessed when touching later array elements, which is undefined behaviour. 然后,您将访问在触摸稍后的数组元素时不应访问的内存,这是未定义的行为。 Depending on various things, that could consistently work as if your code was correct, immediately crash with a segfault or anything in between (technically it could behave in a manner that cannot meaningfully be placed between those two, but that would be unusual). 根据各种各样的事情,可以始终如一地工作,好像你的代码是正确的,立即崩溃与段错误或介于两者之间的任何东西(从技术上讲,它可能表现得不能有意义地放在这两者之间,但这将是不寻常的)。

If you intentionally do that, knowing point 1. or 2. applies, it's bad practice, but not an error. 如果你有意这样做,知道点1或2.适用,这是不好的做法,但不是错误。 If you do it unintentionally, it is an error regardless of which point applies, harmless but hard to find while 1. or 2. applies, harmful but normally easier to detect in case of 3. 如果你无意中这样做,那么无论哪个点适用都是错误的,无害但很难找到1.或2.适用,有害但通常在3的情况下更容易检测。

In your examples. 在你的例子中。 data was 4 resp. data是4分。 8 bytes (probably), which on a 64-bit system puts them into 1. resp. 8个字节(可能),在64位系统上将它们放入1. resp。 2. with high probability, on a 32-bit system into 2 resp. 2.概率很高,在32位系统上分为2分。 3. 3。

The recommended way to avoid such errors is to 避免此类错误的推荐方法是

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

This array = (data *)malloc(sizeof(data *) * n) allocates a sizeof(data*) ( pointer ) to struct data , if you want to do that, you need a your array to be a data** array . 这个array = (data *)malloc(sizeof(data *) * n)为struct data分配sizeof(data*)指针 ),如果你想这样做,你需要一个你的array作为data** array

In your case you want your pointer to point to sizeof(data) , a structure in memory, not to another pointer. 在您的情况下,您希望指针指向sizeof(data) ,内存中的结构,而不是指向另一个指针。 That would require a data** (pointer to pointer). 这将需要data** (指向指针的指针)。

is it valid to assign that to struct a * instead of struct a ** ? 将它赋给struct a *而不是struct a **是否有效?

Well, technically speaking, it is valid to assign like that, but it is wrong (UB) to dereference such pointer. 好吧,从技术上讲,这样分配是有效的,但取消引用这样的指针是错误的(UB)。 You don't want to do this. 你不想这样做。

valid to access/de-reference the allocated array(n-elements)-of-pointers-to-type-"struct a" using pointer-to-"struct a" ? 有效访问/取消引用已分配的数组(n元素)-of-pointers-to-type-“struct a”使用指针到“struct a”?

No, undefined behavior. 不,未定义的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM