簡體   English   中英

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

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

這個問題是Malloc調用崩潰的延續,但在其他地方有效

我嘗試了以下程序,我發現它工作(即沒有崩潰 - 這也在上面提到的鏈接中提到)。 我很幸運能讓它工作但是我正在尋找SO專家對於它為什么有效的合理解釋?!

以下是使用malloc() wrt structurespointers分配memory一些基本知識

  • malloc(sizeof(struct a) * n)分配n個類型struct a元素。 並且,可以使用pointer-to-type-"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. 有效訪問/取消引用已分配的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; 
}   

代碼段如下:

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

編輯:好的,如果我錯誤地執行了以下操作

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

有沒有辦法捕獲(在使用任何GCC標志的編譯時)這些無意識的編程錯字,它可能有時會工作,並可能隨時爆發! 我用-Wall編譯了這個,發現沒有警告!

沒有。

sizeof(struct a*)指針的大小。
sizeof(struct a)是整個struct的大小。

似乎存在一個根本性的誤解。

malloc(sizeof(struct a)* n)分配n個類型struct a元素。

不,這就是人們通常在這樣的電話之后使用它的原因。 malloc(size)分配size bytes的內存區域。 你對該地區的所作所為完全取決於你。 唯一重要的是你不要超越分配內存的限制。 假設4個字節的floatint以及8個字節的double ,在成功的malloc(100*sizeof(float)); ,您可以使用400字節中的前120個作為15個double s的數組,接下來的120作為30個float的數組,然后在其后面放置一個20個char的數組,並用35填充剩余的140個字節int如果你想秒。 這是完全無害的定義行為。

malloc返回一個void* ,它可以隱式地轉換為任何類型的指針,所以

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

非常好,它可能不是你想要的記憶量。 在這種情況下很可能是因為指針往往具有相同的大小,而不管它們指向的是什么。

更容易給你錯誤的內存量

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

就像你擁有它一樣。 如果將分配的內存塊用作n data類型元素的數組,則有三種可能性

  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. resp。 2.概率很高,在32位系統上分為2分。 3。

避免此類錯誤的推薦方法是

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

這個array = (data *)malloc(sizeof(data *) * n)為struct data分配sizeof(data*)指針 ),如果你想這樣做,你需要一個你的array作為data** array

在您的情況下,您希望指針指向sizeof(data) ,內存中的結構,而不是指向另一個指針。 這將需要data** (指向指針的指針)。

將它賦給struct a *而不是struct a **是否有效?

好吧,從技術上講,這樣分配是有效的,但取消引用這樣的指針是錯誤的(UB)。 你不想這樣做。

有效訪問/取消引用已分配的數組(n元素)-of-pointers-to-type-“struct a”使用指針到“struct a”?

不,未定義的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM