从在声明灵活数组成员时使用正确的语法它说,当被黑客入侵时,何时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;
}
印刷,
<Foo> <To be or >
兼容的解决方案使用C99
灵活的数组成员。该页面还说,
在声明灵活数组成员时未能使用正确的语法可能会导致未定义的行为,尽管错误的语法适用于大多数实现。
从技术上讲,这段C90
代码是否也会产生未定义的行为?如果不是,有什么区别?(或者 Carnegie Mellon Wiki 不正确?)在实现上这不起作用的因素是什么?