单个 malloc 中的多个结构调用未定义的行为?

2024-01-01

From 声明灵活数组成员时使用正确的语法 https://wiki.sei.cmu.edu/confluence/display/c/DCL38-C.+Use+the+correct+syntax+when+declaring+a+flexible+array+member它说当malloc用于标题和灵活数据时data[1]被黑客入侵struct,

此示例在访问其他任何元素时具有未定义的行为 比数据数组的第一个元素。 (参见 C 标准,6.5.6。) 因此,编译器可以生成不返回 访问数据的第二个元素时的预期值。

我查阅了 C 标准 6.5.6,但看不出这会如何产生未定义的行为。我使用了一种我喜欢的模式,其中标题后面隐式跟随数据,使用相同类型的malloc,

#include <stdlib.h> /* EXIT malloc free */
#include <stdio.h>  /* printf */
#include <string.h> /* strlen memcpy */

struct Array {
    size_t length;
    char *array;
}; /* +(length + 1) char */

static struct Array *Array(const char *const str) {
    struct Array *a;
    size_t length;
    length = strlen(str);
    if(!(a = malloc(sizeof *a + length + 1))) return 0;
    a->length = length;
    a->array = (char *)(a + 1); /* UB? */
    memcpy(a->array, str, length + 1);
    return a;
}

/* Take a char off the end just so that it's useful. */
static void Array_to_string(const struct Array *const a, char (*const s)[12]) {
    const int n = a->length ? a->length > 9 ? 9 : (int)a->length - 1 : 0;
    sprintf(*s, "<%.*s>", n, a->array);
}

int main(void) {
    struct Array *a = 0, *b = 0;
    int is_done = 0;
    do { /* Try. */
        char s[12], t[12];
        if(!(a = Array("Foo!")) || !(b = Array("To be or not to be."))) break;
        Array_to_string(a, &s);
        Array_to_string(b, &t);
        printf("%s %s\n", s, t);
        is_done = 1;
    } while(0); if(!is_done) {
        perror(":(");
    } {
        free(a);
        free(b);
    }
    return is_done ? EXIT_SUCCESS : EXIT_FAILURE;
}

Prints,

<Foo> <To be or >

合规解决方案使用C99灵活的数组成员。该页面还说,

声明灵活数组时未能使用正确的语法 尽管语法不正确,但成员可能会导致未定义的行为 将适用于大多数实现。

从技术上讲,这是否C90代码也会产生未定义的行为吗?如果不是,有什么区别? (或者卡内基梅隆维基百科是不正确的?)导致此方法不起作用的实现因素是什么?


这应该得到很好的定义:

a->array = (char *)(a + 1);

因为您创建了一个指向超过大小为 1 的数组末尾的一个元素的指针,但不取消引用它。并且因为a->array现在指向尚未具有有效类型的字节,您可以安全地使用它们。

然而,这只有效,因为您使用后面的字节作为数组char。如果您尝试创建大小大于 1 的其他类型的数组,则可能会遇到对齐问题。

例如,如果您使用 32 位指针为 ARM 编译了一个程序,并且您有以下内容:

struct Array {
    int size;
    uint64_t *a;
};
...
Array a = malloc(sizeof *a + (length * sizeof(uint64_t)));
a->length = length;
a->a= (uint64_t *)(a + 1);       // misaligned pointer
a->a[0] = 0x1111222233334444ULL;  // misaligned write

您的程序会由于未对齐的写入而崩溃。所以一般来说你不应该依赖于此。最好坚持使用标准保证可以工作的灵活阵列成员。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

单个 malloc 中的多个结构调用未定义的行为? 的相关文章

  • 使用 CLion 进行 OpenCV Windows 设置

    我想在 Windows 上为 CLion IDE 设置 OpenCV 我尝试使用 OpenCV 3 1 和 2 4 得到相同的结果 我有 Windows 10 64 位 CLion 使用 cygwin 环境 到目前为止我做了什么 1 从Op
  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • json.net自定义jobject反序列化

    我正在尝试使用 JsonConvert DeserializeObject string 将字符串反序列化为可与动态一起使用的 jobject 来动态访问 json 文档 但是我想避免知道文档的大小写 以便我可以输入 dynamic doc
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • 在 Java 中创建 T 的新实例

    在C 中 我们可以定义一个泛型class A
  • linq 中使用字符串数组 c# 的 'orderby'

    假设我有一个这样的方法定义 public CustomerOrderData GetCustomerOrderData string CustomerIDs var query from a in db Customer join b in
  • 从模板切换传递的类型

    在 C 中是否可以检查传递给模板函数的类型 例如 template
  • 是否存在指向不同类型的指针具有不同大小的平台?

    C 标准允许指向不同类型的指针具有不同的大小 例如sizeof char sizeof int 是允许的 但是 它确实要求如果将指针转换为void 然后转换回其原始类型 它必须与其原始值进行比较 因此 从逻辑上来说 sizeof void
  • 计算另一个表达式中的 C# 表达式

    我想在另一个表达式中使用一个表达式 Expression
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • 如何在三个 IEnumerable 上使用 Zip [重复]

    这个问题在这里已经有答案了 可能的重复 使用 Linq 从 3 个集合创建项目 https stackoverflow com questions 5284315 create items from 3 collections using
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 在 asp.net MVC 中使用活动目录进行身份验证

    我想使用活动目录对我的 asp net mvc 项目中的用户进行身份验证 在网上冲浪了几个小时后 我没有找到任何对我有用的东西 我已经看到了所有结果 但什么也没有 我尝试按照许多帖子的建议编辑我的 web config 如果有人可以帮助我提
  • 如何使用 NPOI 按地址(A1、A2)获取 Excel 单元格值

    我有一个 Excel 单元格地址 例如 A1 A2 如何使用 C 中的 NPOI 框架以编程方式访问此单元格 我找到的一些 Java POI 示例代码 CellReference cr new CellReference A1 row my
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • 使用 jQuery 从 ASP.Net JSON 服务获取数据

    我正在尝试调用 Google 地图地理编码 API 从纬度 经度对中获取格式化的地址 然后将其记录到控制台 我正在尝试获取为给定位置返回的第一个 formatted address 项目 我很简单无法从 JSON 中提取该项目 我不知道为什
  • 在 C#.NET 中安全删除文件

    在我正在做的一个项目中 我想为用户提供 安全 删除文件的选项 例如 用随机位或 0 覆盖它 在 C NET 中是否有一种简单的方法可以做到这一点 效果如何 你可以调用系统内部删除 http technet microsoft com en
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan
  • 为什么匹配模板类上的部分类模板特化与没有模板匹配的另一个部分特化不明确?

    这个问题可能很难用标题中的句子来描述 但这里有一个最小的例子 include

随机推荐