在C中的malloc’d字符串之前保留元数据是否安全?

我很想知道在字符串周围保留元数据标题是否安全且不依赖于实现?

我不确定以下内容是否可以跨平台工作,或者是否有可能导致读取错误大小或总字段的内容,或者是否在缓冲区上执行realloc时出现问题?

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

typedef struct{
    int size;
    int total;
    char buf[];
} String;

int get_str_size(char *str){
    String *pointer = (void*)(str-sizeof (String));
    return pointer->size;
}

int get_str_total(char *str){
    String *pointer = (void*)(str-sizeof (String));
    return pointer->total;
}

char *init_string(int sz){
    size_t header_size = 1 + sz + sizeof(String);
    String *pointer = calloc(header_size, 1);

    pointer->total = 0;
    pointer->size = sz;

    return pointer->buf;
}

char *realloc_string(char *str, int sz){
    int old = get_str_size(str);
    int new = old + sz;

    String *pointer1 = (void*)(str-sizeof (String));
    size_t header_size = 1 + new + sizeof(String);
    String *pointer2 = realloc(pointer1, header_size);

    return pointer2->buf;
}

int main(void){
    char *str = NULL;
    str = init_string(10);

    printf("Length of str:%d\n", get_str_size(str));
    printf("Total malloc'd:%d\n", get_str_total(str));
    free(str - sizeof (String));

    return 0;
}

最佳答案 这不安全.

它没有未定义的行为(UB)也没有实现定义的行为,因为这是合法的,除了一个小的int / size_t问题.

不幸的是,代码隐藏得太多了. @Jonathan Leffler.考虑以下编译但代码调用UB的代码.

printf("%d\n", get_str_size("Hello Word"));

使用String类型作为参数而不是char *,函数集会更好.这就是类型检查的用途.

小问题.

C字符串是数组.使用type size_t最好使用数组索引. int可能太窄了.

String *String_copy(const char *src) {
  size_t len = strlen(src);
  //                         v-v Overflow potential
  String *dest = init_string(len);
  ...
  return dest;
}

以下可能会溢出.重新订购以防止.

//                      v----v  int math
// size_t header_size = 1 + sz + sizeof(String);
size_t header_size = sz + sizeof(String) + 1;
// or 
size_t header_size = sizeof(String) + sz + 1;

代码缺少应该补充集合的其他函数. @Ian

缺少错误检查,但假设这是为了简化代码显示.

点赞