键入修剪和已分配的内存

时间:2019-05-31 20:34:18

标签: c

我最初问的是这个问题:Type Punning with Unions and Heap

又不想让问题继续发展到将来任何人都不知道原始问题是什么的程度,我有一个副题。

阅读本网站后: https://kristerw.blogspot.com/2016/05/type-based-aliasing-in-c.html

在底部附近讨论了malloc的内存。可以肯定地说,当堆中有内存时,从一种指针类型转换为另一种指针类型是安全的吗?

示例:

#include <stdio.h>
#include <stdlib.h>

struct test1
{
    int a;
    char b;
};

struct test2
{
    int c;
    char d;
};

void printer(const struct test2* value);

int main()
{
    struct test1* aQuickTest = malloc(sizeof(struct test1));
    aQuickTest->a = 42;
    aQuickTest->b = 'a';
    printer((struct test2*)aQuickTest); //safe because memory was malloc'd???
    return 0;
}

void printer(const struct test2* value)
{
    printf("Int: %i Char: %c",value->c, value->d);
}

猜测可能并不安全。用memcpy执行此操作的正确方法是什么?我将尝试编写一个示例,其中包含希望能起作用的功能?

struct test2* converter(struct test1* original);

int main()
{
    struct test1* aQuickTest = malloc(sizeof(struct test1));
    aQuickTest->a = 42;
    aQuickTest->b = 'a';
    struct test2* newStruct = converter(aQuickTest);
    printer(newStruct);
    return 0;
}

struct test2* converter(struct test1* original)
{
    struct test2* temp;
    memcpy(&temp, &original, sizeof(struct test2));
    return temp;
}

1 个答案:

答案 0 :(得分:3)

void *pnt = malloc(sizeof(struct test1));

pnt指针后面的存储器有什么类型?没有类型它是未初始化的(其值为“不确定”)。只有“记忆”。

然后您这样做:

struct test1* aQuickTest = malloc(sizeof(struct test1));

您只投下了指针。这里什么都没有发生。没有生成程序集。读取未初始化的内存是未定义的行为,因此您无法从aQuickTest->a进行读取(尚未)。但是您可以分配:

aQuickTest->a = 1;

这将写入内存中的对象struct test1。这是作业。您现在可以阅读aQuickTest->a,即。打印。
但是以下

printf("%d", ((struct test2*)aQuickTest)->a);

是未定义的行为(尽管它将/应该起作用)。您使用不匹配的指针类型struct test1访问基础对象(即struct test2*)。这称为“严格别名违反”。使用非compatible type的句柄取消引用对象(即执行->*)会导致未定义的行为。 struct test1struct test2“看起来相同”并不重要。它们是不同的类型。规则在C11 standard 6.5p7中。

在第一个代码中,在printf("Int: %i Char: %c",value->c内部发生了未定义的行为。访问value->使用不兼容的句柄访问基础内存。

在第二段代码中,变量temp仅是一个指针。 original也是一个指针。进行memcpy(&temp, &original, sizeof(struct test2));是无效的,因为&temp写入temp指针,而&original写入original pointer. No to the memory behind pointers. As you write out of bounds into&temp pointer and read of bounds from&original pointer (because most probably sizeof(temp)and sizeof(原始)

无论如何:

    struct test1* original = &(some valid struct test1 object).
    struct test2 temp;
    memcpy(&temp, original, sizeof(struct test2));
    printf("%d", temp.a); // undefined behavior

访问 temp变量后面的内存仍然无效。由于original没有struct test2对象,因此它仍然无效。 memcpy不会更改内存中对象的类型。