- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
当指针悬空时,SO 上出现了一个问题,询问“为什么这样工作”。答案是它是 UB,这意味着它可能有效也可能无效。
我在教程中了解到:
#include <iostream>
struct Foo
{
int member;
void function() { std::cout << "hello";}
};
int main()
{
Foo* fooObj = nullptr;
fooObj->member = 5; // This will cause a read access violation but...
fooObj->function(); // Because this doesn't refer to any memory specific to
// the Foo object, and doesn't touch any of its members
// It will work.
}
这是否等同于:
static void function(Foo* fooObj) // Foo* essentially being the "this" pointer
{
std::cout << "Hello";
// Foo pointer, even though dangling or null, isn't touched. And so should
// run fine.
}
我错了吗?即使正如我所解释的那样只是调用一个函数而不访问无效的 Foo 指针,它是否是 UB?
最佳答案
您正在推理实践中发生的事情。允许未定义的行为做你期望的事情......但不能保证。
对于非静态情况,使用 [class.mfct.non-static]
中的规则可以直接证明:
If a non-static member function of a class
X
is called for an object that is not of typeX
, or of a type derived fromX
, the behavior is undefined.
请注意,没有考虑非静态成员函数是否访问*this
。该对象只需要具有正确的动态类型,而 *(Foo*)nullptr
当然不需要。
特别是,即使在使用您描述的实现的平台上,调用
fooObj->func();
转换为
__assume(fooObj); Foo_func(fooObj);
并且优化不稳定。
这是一个与您的预期相反的示例:
int main()
{
Foo* fooObj = nullptr;
fooObj->func();
if (fooObj) {
fooObj->member = 5; // This will cause a read access violation!
}
}
在真实的系统上,这很可能以注释行的访问冲突结束,因为编译器使用了 fooObj
can't be null 的事实fooObj->func()
以消除其后的 if
测试。
即使您认为自己了解平台的功能,也不要做不合理的事情。 Optimization instability is real.
此外,该标准比您想象的更加严格。这将也导致 UB:
struct Foo
{
int member;
void func() { std::cout << "hello";}
static void s_func() { std::cout << "greetings";}
};
int main()
{
Foo* fooObj = nullptr;
fooObj->s_func(); // well-formed call to static member,
// but unlike Foo::s_func(), it requires *fooObj to be a valid object of type Foo
}
标准的相关部分可在[expr.ref]
中找到:
The expression
E1->E2
is converted to the equivalent form(*(E1)).E2
和随附的脚注
If the class member access expression is evaluated, the subexpression evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.
这意味着有问题的代码肯定会评估 (*fooObj)
,试图创建对不存在对象的引用。已经有几个提议允许并且只禁止在这样的引用上允许左值->右值转换,但到目前为止这些都被拒绝了;在迄今为止的所有标准版本中,即使形成引用也是非法的。
关于c++ - C++ 中的这种未定义行为是从悬空指针调用函数吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49213446/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
指针, C语言的精髓 莫队先咕几天, 容我先讲完树剖 (因为后面树上的东西好多都要用树剖求 LCA). 什么是指针 保存变量地址的变量叫做指针. 这是大概的定义, 但是Defad认为
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我是一名优秀的程序员,十分优秀!