这个问题是Malloc调用崩溃的延续,但在其他地方有效
我尝试了以下程序,发现它可以工作(即不会崩溃 - 上面提到的链接中也提到了这一点(。我可能很幸运能让它工作,但我正在寻找 SO 专家关于为什么它有效的合理解释?!
以下是使用malloc()
w.r.t structures
和pointers
分配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"
时,是不是
- 将其分配给
struct a *
而不是struct a **
有效? - 使用
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 字节float
和 int
和 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*));
就像你一样。如果使用分配的内存块作为类型 data
的 n
元素数组,则有三种可能性
-
sizeof(data) < sizeof(data*)
.那么你唯一的问题是你在浪费一些空间。 -
sizeof(data) == sizeof(data*)
.一切都很好,没有浪费空间,好像你根本没有错别字。 -
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"有效?
不,未定义的行为。