Vee*_*eeg 21 c sizeof null-pointer dereference
我遇到了一段代码片段,对我来说应该会因为分段错误而崩溃,但它可以毫无障碍地工作.有问题的代码加上相关的数据结构如下(在上面找到相关的评论):
typedef struct {
double length;
unsigned char nPlaced;
unsigned char path[0];
}
RouteDefinition* Alloc_RouteDefinition()
{
// NB: The +nBags*sizeof.. trick "expands" the path[0] array in RouteDefinition
// to the path[nBags] array
RouteDefinition *def = NULL;
return (RouteDefinition*) malloc(sizeof(RouteDefinition) + nBags * sizeof(def->path[0]));
}
Run Code Online (Sandbox Code Playgroud)
为什么这样做?我收集了的sizeof的字符*将解决对给定的体系结构指针的大小,但它不应该和好如初,同时取消引用NULL终场?
Sha*_*our 16
为什么这样做?
这是有效的,因为sizeof是一个编译时构造,但根本不评估可变长度数组.如果我们看看C99草案标准部分6.5.3.4 ,运营商第2段的尺寸说明(强调我的):
[...]大小由操作数的类型决定.结果是整数.如果操作数的类型是可变长度数组类型,则计算操作数; 否则,不评估操作数,结果是整数常量.
我们还看到第5段中的以下例子证实了这一点:
double *dp = alloc(sizeof *dp);
^^^ ^
|
This is not the use of uninitialized pointer
Run Code Online (Sandbox Code Playgroud)
在编译时,要确定表达式的类型以便计算结果.我们可以通过以下示例进一步证明这一点:
int x = 0 ;
printf("%zu\n", sizeof( x++ ));
Run Code Online (Sandbox Code Playgroud)
它不会增加x,这是非常整洁的.
更新
正如我在注意我的回答对为什么的sizeof(X +)不增加x?sizeof编译时操作有一个例外,那就是它的操作数是一个可变长度数组(VLA).虽然我之前没有指出它,但6.5.3.4上面引用的确如此.
虽然在C11中与C99相反,但未指明sizeof在这种情况下是否进行评估.
另外,请注意这个问题的C++版本:不评估应用sizeof的表达式使得在C++中取消引用sizeof中的null或无效指针是合法的吗?.
Som*_*ude 10
该sizeof运营商是一个纯粹的编译时操作.什么都没有运行时,这就是为什么它工作正常.
顺便说一句,该path成员实际上并不是一个指针,所以它在技术上是不可能的NULL.
| 归档时间: |
|
| 查看次数: |
4528 次 |
| 最近记录: |