是"的malloc(sizeof的(结构A *))"和"的malloc(sizeof的(结构A))"一样? [英] Are "malloc(sizeof(struct a *))" and "malloc(sizeof(struct a))" the same?

查看:182
本文介绍了是"的malloc(sizeof的(结构A *))"和"的malloc(sizeof的(结构A))"一样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这问题是一个 malloc调用崩溃的延续,但在其他地方工作

我尝试下面的程序,我发现它的工作(即不崩溃 - 这是在上述提到的链接太)。我可能是幸运,它的工作,但我正在寻找从SO专家为什么这是工作一个合理的解释?!

下面是关于内存使用的malloc() WRT 结构分配的一些基本认识指针


  • 的malloc(sizeof的(结构A)* N)中分配 N 类型的数结构体在元素。而且,该内存位置可以存储并使用访问的指针到类型 - 结构是。基本上一个结构A *

  • 的malloc(sizeof的(结构A *)* N)中分配 N 类型的数结构体一* 元素。然后,每个元素都可以指向类型的元素结构A 。基本上的malloc(sizeof的(结构A *)* N)分配一个阵列(正元素)-of球到类型 - 结构一个。而且,分配的内存位置可以存储并使用指针访问于─(指针于─结构A)。基本上一个结构一个**

所以,当我们创建一个阵列(正元素)-of球到类型 - 结构是,它是


  1. 的有效分配,为结构A * 而不是结构一个**

  2. 的有效访问/去参考分配阵列(正元素)-of球到类型 - 结构是使用指针于─结构是

 数据*阵列= NULL;如果((阵列=(数据*)malloc的(sizeof的(数据*)* N))== NULL){
    的printf(无法分配内存\\ n);
    返回-1;
}

在code片断如下:

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;INT主要(无效)
{
    typedef结构{
        INT值1;
        INT值2;
    }数据;    INT N = 1000;
    INT I;
    INT VAL = 0;    数据*阵列= NULL;    如果((阵列=(数据*)malloc的(sizeof的(数据*)* N))== NULL){
        的printf(无法分配内存\\ n);
        返回-1;
    }
    的printf(分配成功\\ n);    对于(i = 0; I< N;我++){
        数组[我] .value1 = VAL ++;
        数组[我] .value2 = VAL ++;
    }    对于(i = 0; I< N;我++){
        的printf(%3D%3D%3D \\ n,我,阵列[我] .value1,数组[I] .value2);
    }    免费(数组);
    的printf(解放成功\\ n);    返回0;
}


编辑:
OK说,如果我这样做遵循的错误

 数据*阵列= NULL;
如果((阵列=(数据*)malloc的(sizeof的(数据*)* N))== NULL){

有没有一种方法来捕捉(在编译时使用任何 GCC 标记)这类意外编程错字的可能有时工作,并可能会随时吹出来的!我使用这个 -Wall 并没有发现任何警告编译!


解决方案

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


  

的malloc(sizeof的(结构A)* N)分配型的N多一个结构元素。


没有,这正是人们通常不使用它作为这样的电话后。 的malloc(大小)分配的尺寸字节的内存区域。你与该地区做的是完全取决于你。唯一重要的事情是,你不逾越分配的内存的限制。假设4个字节浮动 INT 和8字节双击,一个成功的的malloc(100 * sizeof运算(浮点))之后; ,则可以使用400字节的第一个120的15数组 S,30 浮动数组的下一个120 S,然后把20的阵列字符没错落后,如果你想填补剩余的140个字节,35 INT 秒。这是完全无害的定义的行为。

的malloc 返回无效* ,可以隐式转换为任何类型的指针,因此

  some_type **阵列=的malloc(100 * sizeof的(数据*)); //故意不相关的类型

是完全正常的,它可能只是没有记忆你想要的金额。在这种情况下,它很可能是,因为指针往往具有相同的大小,而不管他们是指向什么。

更可能给你的内存错误量

 数据*阵列=的malloc(N * sizeof的(数据*));

你有它。如果使用分配一块内存作为 N 类型的元素数据,有三种可能性


  1. 的sizeof(数据)<的sizeof(数据*)。那么你唯一的问题是,你浪费了一些空间。

  2. 的sizeof(数据)==的sizeof(数据*)。一切都很好,没有空间浪费,因为如果你没有错字的。

  3. 的sizeof(数据)>的sizeof(数据*)。然后你会触摸访问后数组元素,这是不确定的行为时,你不应该访问的存储器。根据不同的事情,这可能一致地工作,如果你的code是正确的,应立即用之间(在技术上它可能会在无法有意义放在这两个之间的行为方式段错误或任何崩溃,但是这将是不寻常)。

如果您有意这样做,知道点1或2适用,它的的做法,但不是一个错误。如果你这样做无意的,这是一个错误无论哪个点适用,无害的,但很难找到,而1或2适用的,有害的,但通常更容易在3例检测。

在你的例子。 数据为4 RESP。 8个字节(可能),它在64位系统上的将其放入1 RESP。 2.以很高的概率,在32位系统上为2,分别3。

推荐的方式,以避免这样的错误是

 键入*指针=的malloc(num_elems * sizeof的(*指针));

This question is a continuation of Malloc call crashing, but works elsewhere

I tried the following program and I found it working (i.e. 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?!

Here are some basic understanding on allocation of memory using malloc() w.r.t structures and pointers

  • malloc(sizeof(struct a) * n) allocates n number of type struct a elements. And, this memory location can be stored and accessed using a pointer-to-type-"struct a". Basically a struct a *.
  • malloc(sizeof(struct a *) * n) allocates n number of type struct a * elements. Each element can then point to elements of type struct a. Basically malloc(sizeof(struct a *) * n) allocates an 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"). Basically a struct a **.

So when we create an array(n-elements)-of-pointers-to-type-"struct a", is it

  1. valid to assign that to struct a * instead of struct a ** ?
  2. valid to access/de-reference the allocated array(n-elements)-of-pointers-to-type-"struct a" using 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! I compiled this using -Wall and found no warnings!

解决方案

There seems to be a fundamental misunderstanding.

malloc(sizeof(struct a) * n) allocates n number of type struct a elements.

No, that's just what one usually does use it as after such a call. malloc(size) allocates a memory region of 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));, you can use the first 120 of the 400 bytes as an array of 15 doubles, the next 120 as an array of 30 floats, then place an array of 20 chars right behind that and fill up the remaining 140 bytes with 35 ints if you wish. That's perfectly harmless defined behaviour.

malloc returns a void*, which can be implicitly cast to a pointer of any type, so

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

  1. sizeof(data) < sizeof(data*). Then your only problem is that you're wasting some space.
  2. sizeof(data) == sizeof(data*). Everything's fine, no space wasted, as if you had no typo at all.
  3. 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. 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.

In your examples. data was 4 resp. 8 bytes (probably), which on a 64-bit system puts them into 1. resp. 2. with high probability, on a 32-bit system into 2 resp. 3.

The recommended way to avoid such errors is to

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

这篇关于是&QUOT;的malloc(sizeof的(结构A *))&QUOT;和&QUOT;的malloc(sizeof的(结构A))&QUOT;一样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆