首先,澄清一点,我不是在谈论解除引用无效指针!
考虑以下两个例子.
例1
typedef struct { int *p; } T;
T a = { malloc(sizeof(int) };
free(a.p); // a.p is now indeterminate?
T b = a; // Access through a non-character type?
Run Code Online (Sandbox Code Playgroud)
例2
void foo(int *p) {}
int *p = malloc(sizeof(int));
free(p); // p is now indeterminate?
foo(p); // Access through a non-character type?
Run Code Online (Sandbox Code Playgroud)
题
以上示例中的任何一个都会调用未定义的行为吗?
上下文
提出这个问题是为了回应这一讨论.建议是,例如,指针参数可以通过x86段寄存器传递给函数,这可能导致硬件异常.
根据C99标准,我们学习以下内容(强调我的):
[3.17] 不确定值 - 未指定的值或陷阱表示
然后:
[6.2.4 p2]当指向的对象到达其生命周期的末尾时,指针的值变得不确定.
然后:
[6.2.6.1 p5]某些对象表示不需要表示对象类型的值.如果对象的存储值具有这样的表示并且由不具有字符类型的左值表达式读取,则行为是未定义的.如果这样的表示是由副作用产生的,该副作用通过不具有字符类型的左值表达式修改对象的全部或任何部分,则行为是未定义的.这种表示称为 …
考虑以下程序:
#include <iostream>
int const * f(int const &i)
{
return &i;
}
int main()
{
std::cout << f(42); // #1
std::cout << f(42); // #2
std::cout << f(42) << f(42); // #3
}
Run Code Online (Sandbox Code Playgroud)
根据编译器和设置的优化级别,打印在行上的地址可能彼此不同#1,#2也可能不同。
但是,无论选择何种编译器或优化级别,行#3中打印的 2 个地址总是彼此不同。
这是一个可以玩的演示。
那么f在每种情况下返回什么的规则是什么?
我的大小是1.不应该是4吗?我将整数的地址插入集合中.
void func(set<int*>& s1, set<int*>& s2, int a)
{
s1.insert(&a);
s2.insert(&a);
}
int main()
{
set<int*> s1, s2;
int a = 1, b = 2, c = 3, d = 4;
func(s1, s2, a);
func(s1, s2, b);
func(s1, s2, c);
func(s1, s2, d);
cout<<" s1.size = "<<s1.size()<<" s2.size = "<<s2.size()<<endl;
}
Run Code Online (Sandbox Code Playgroud) 我正在遍历带有auto(附加代码)的向量.在遍历时,我还在后面添加了一些元素.我没想到我得到的输出.
#include <iostream>
#include <vector>
using namespace std;
vector <int> dynamic_vector;
void access( )
{
for ( auto i : dynamic_vector ) {
if ( i == 3 ) {
dynamic_vector.push_back( 4 );
dynamic_vector.push_back( 5 );
}
cout << i << endl;
}
}
int main() {
dynamic_vector.push_back( 1 );
dynamic_vector.push_back( 2 );
dynamic_vector.push_back( 3 );
access( );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
1
2
3
Run Code Online (Sandbox Code Playgroud)
我期待从1到5的所有数字都会被打印出来.我无法理解如何遍历汽车工作?
在同一时间,我创建了一个指针指向std::vector,然后我做了一些push_back,reserve,resize操作与向量,这样的操作之后,是安全的指针比较的是向量的地址,以检查是否指针指向该向量,因为可能会有一些内存重新分配.
例如
std::vector<int> vec;
vector<int>* pVec = &vec;
vec.reserve(10000);
assert(pVec == &vec);
vec = anotherVec;
assert(pVec == &vec);
Run Code Online (Sandbox Code Playgroud)
更重要的是,将指针与向量的第一个值进行比较是否安全?例如:
std::vector<int> vec(1,0);
int* p = &vec[0];
// some operation here
assert(p == &vec[0]);
Run Code Online (Sandbox Code Playgroud)
正如我自己测试的那样,第一种情况似乎是安全的,而第二种情况则不然,但我不能确定.
Fox例子:
int* a = new int[10];
int* b = a;
int* e = a + 10;
delete[] a;
for (; b != e; ++b);
Run Code Online (Sandbox Code Playgroud)
我知道解除引用无效指针将是UB.但是如何比较和增加呢?
背景
这是一个问题,OP在基于范围的for循环中添加元素,这可能导致迭代器变为无效.但是他最后在向量中添加了元素,之后迭代器将被增加并进行比较,而不是解除引用.是UB吗?
是否可以使用指向"if"语句中声明的变量的地址的指针?示例如下:
...
int *pTest = 0;
if (...)
{
int x = 10;
pTest = &x;
}
else
{
int x = 100;
pTest = &x;
}
...
// use pTest
Run Code Online (Sandbox Code Playgroud) int a = 10;
int* ptrA = &a;
int* ptrB = &a;
delete ptrA;
return 0;
Run Code Online (Sandbox Code Playgroud)
这不应该导致泄漏,导致mem/data被释放ptrA,但是我们有2个指向有效地址的指针,其数据刚被删除?它是如何工作的?