【发布时间】:2021-12-16 05:55:06
【问题描述】:
有人可以向我解释为什么下面的代码在带有 -O2 标志的 clang 13 中得到了奇怪的优化吗?使用带有 clang 的较低优化设置和 gcc 的所有优化设置,我得到预期的打印输出“John:5”,但是,使用 clang -O2 或更大的优化标志,我得到“:5”的输出。我的代码是否有我不知道的未定义行为?奇怪的是,如果我使用 -fsanitize=undefined 编译代码,代码将按预期工作。我什至应该如何尝试诊断这样的问题?非常感谢任何帮助。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef size_t usize;
typedef struct String {
char *s;
usize len;
} String;
String string_new(void) {
String string;
char *temp = malloc(1);
if (temp == NULL) {
printf("Failed to allocate memory in \"string_new()\".\n");
exit(-1);
}
string.s = temp;
string.s[0] = 0;
string.len = 1;
return string;
}
String string_from(char *s) {
String string = string_new();
string.s = s;
string.len = strlen(s);
return string;
}
void string_push_char(String *self, char c) {
self->len = self->len + 1;
char *temp = realloc(self->s, self->len);
if (temp == NULL) {
printf("Failed to allocate memory in \"string_push_char()\".\n");
exit(-1);
}
self->s[self->len - 2] = c;
self->s[self->len - 1] = 0;
}
void string_free(String *self) {
free(self->s);
}
int main(void) {
String name = string_new();
string_push_char(&name, 'J');
string_push_char(&name, 'o');
string_push_char(&name, 'h');
string_push_char(&name, 'n');
printf("%s: %lu\n", name.s, name.len);
string_free(&name);
return 0;
}
【问题讨论】:
-
您的
string_from看起来很奇怪。为什么要分配输入指针而不是分配+strcpy()?这也导致了内存泄漏:原来的string.s丢失了并且永远不会被释放。 -
如果两个编译器生成的代码行为不同,那么这通常表明您的代码中有一些未定义的行为。
-
在您的
string_push_char中,您永远不会将temp分配回self->s。但是realloc不保证内存会和以前一样。关于“我什至应该如何尝试诊断这样的问题” - 有时仔细阅读代码会有所帮助 -
另外,
realloc不一定返回相同的指针 - 可以根据需要移动数据。您应该将realloc的结果分配回self->s。
标签: c gcc clang undefined-behavior