我创建了一个我在iOS应用程序的ViewDidLoad中指定的成员结构。我使用malloc为这个结构分配空间,然后在我的课程中使用它。像这样:
self.myData = malloc(sizeof(MyData));
除了我真正做的是这个:
self.myData = malloc(sizeof(MyOtherStruct));
我不小心将malloc调用中的sizeof()设置为不同的结构(大小不同)。我很长时间没有注意到这个错误,因为应用程序很少崩溃。对操作系统的更新导致崩溃更频繁发生。
我的问题是,为什么编译器不会对这类事情发出警告?这是编译器不知道的东西,或者它是一种设计选择,允许用户使用它们喜欢的任何尺寸吗?
答案 0 :(得分:4)
“如何更快地找到此错误?”
有很多方法可以更快地找到错误。
静态分析器发现此错误。在Xcode中按下命令shift-B。例如,请使用以下代码:
#include <stdlib.h>
struct x { double x; };
struct y { char y; };
int main(int argc, char **argv) {
struct x *p = malloc(sizeof(struct y));
p->x = 1.0;
return 0;
}
运行分析器会为我生成此错误:
'malloc'的结果被转换为'struct x'类型的指针,该指针与sizeof操作数类型'struct y'不兼容
建议以这种方式编写代码:
self.myData = malloc(sizeof(*self.myData));
将来这样做吧。这不仅容易出错,而且更容易记住。
使用像Swift或C ++这样的语言,语言的类型系统可以帮助您避免这种错误。 C在很多方面都不太宽容。它是在20世纪70年代早期发明的,你只需要接受它,如果你想使用它,这些类型的错误是主要的部分原因C ++和Swift甚至存在于第一名。
使用运行时内存边界检查程序,如地址清理程序。这将在访问内存时检测错误,而不是在分配时检测错误,但它仍然会为访问和分配提供堆栈跟踪(如果已释放内存,则为空闲)。这些天写C的人应该熟悉地址消毒剂及其朋友tsan,ubsan等。
Valgrind也达到了同样的效果,但地址消毒剂对于常见用例具有更好的用户体验。
编译器只会为您提供类型错误的错误和警告。这不是类型错误,而是运行时错误。编译器可以检测到一些“可能的”运行时错误,但它们的数量非常少。忘记使用malloc()
的返回值......例如,
void f(void) {
malloc(1); // warning
}
编译器没有那么好。
同样,这是C ++和Swift等新语言的推动力,它们具有允许您在错误分配事物时生成错误的类型系统,这也是静态分析的推动力(这是一个棘手的问题)。
答案 1 :(得分:0)
这是因为ARC不负责处理malloc()
甚至free()
ARC只处理分配的对象[Object alloc]
在您的情况下,当您执行self.myData = malloc(sizeof(MyOtherStruct));
时,可以使用以下内容进行解释:
self.myData = malloc(N*sizeof(MyData));
//what can represents self.myData[0]..self.myData[N-1]
最后,请记住,当你使用sizeof()
时,它会告诉你类型的大小,你作为参数传递,在编译时计算。
您可以查看此Here以获取有关对象分配的更多信息
并查看有关link
的Apple文档