当我们运行这段代码时,它正常工作并string constant在屏幕上打印:
char *someFun(){
char *temp = "string constant";
return temp;
}
int main(){
puts(someFun());
}
Run Code Online (Sandbox Code Playgroud)
但是,当我们运行以下类似的代码时,它将无法工作并在屏幕上打印一些垃圾:
char *someFun1(){
char temp[ ] = "string";
return temp;
}
int main(){
puts(someFun1());
}
Run Code Online (Sandbox Code Playgroud)
它背后的原因是什么?本质上,两个函数都做类似的事情(即返回"字符串"),但它们仍然表现不同.这是为什么?
下面的代码向函数传递modify_entry一个指向类型对象的指针,Entry并在函数体内部unique_ptr采用原始指针.但是,指针指向的对象似乎在函数返回后仍然存在.
当我编译这段代码
#include <iostream>
#include <memory>
struct Entry {
Entry(std::string name) : name_(name) { std::cout << "Constructor for " + name_ + '\n'; }
~Entry() { std::cout << "Destructor for " + name_ + '\n'; }
std::string name_;
};
void modify_entry(Entry* e_ptr){
std::cout << "Inside modify_entry()\n";
std::unique_ptr<Entry>{e_ptr}->name_ += " Doe";
}
int main(int argc, const char * argv[])
{
Entry* entry_ptr = new Entry("John");
modify_entry(entry_ptr);
std::cout << "Back from modify_entry()\n";
std::cout << entry_ptr->name_ << …Run Code Online (Sandbox Code Playgroud) 当你释放内存时,指向内存的指针会发生什么?他们立即变得无效吗?如果他们以后再次有效会怎么样?
当然,指针变为无效然后再次变为"有效"的通常情况是将其他对象分配到之前使用的内存,如果使用指针访问内存,那么这显然是未定义的行为.悬空指针内存覆盖了第1课,差不多.
但是如果内存再次对同一个分配有效呢?只有一种标准方式可以实现:realloc().如果你有一个指向malloc()偏移量'd存储块内某处的指针> 1,那么使用realloc()缩小块到小于你的偏移量,显然你的指针变得无效.如果你再次使用realloc()增长块至少覆盖悬空指针指向的对象类型,并且在任何情况下都没有realloc()移动内存块,悬空指针是否再次有效?
这是一个极端的案例,我真的不知道如何解释C或C++标准来解决它.以下是显示它的程序.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
static const char s_message[] = "hello there";
static const char s_kitty[] = "kitty";
char *string = malloc(sizeof(s_message));
if (!string)
{
fprintf(stderr, "malloc failed\n");
return 1;
}
memcpy(string, s_message, sizeof(s_message));
printf("%p %s\n", string, string);
char *overwrite = string + 6;
*overwrite = '\0';
printf("%p %s\n", string, string);
string[4] = '\0';
char *new_string = …Run Code Online (Sandbox Code Playgroud) 我一直在阅读Rust和Go并且我看到这些语言如何处理悬空指针及其引起的问题的细微差别.例如,这是Rust中的一个版本:
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String {
let s = String::from("hello");
&s
}
Run Code Online (Sandbox Code Playgroud)
上面会错误地说,在函数中dangle,s超出范围,我不能返回它的引用!但在Go中,这似乎有点允许吗?
Go中如何处理这样的事情?在Go中创建悬空指针是否容易?如果是这样,我有什么措施来控制它们?
这里出现了一个问题,当一个指针变得晃来晃去时,问"为什么这个工作".答案是它是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.
}
Run Code Online (Sandbox Code Playgroud)
这相当于:
static void function(Foo* fooObj) // Foo* essentially being the "this" pointer
{
std::cout << "Hello";
// Foo …Run Code Online (Sandbox Code Playgroud) 在目标 C 中,我们可以向nil对象发送消息。
Zoombie(悬空指针)对象是一个指向其内存被释放的对象的对象。即不指向任何有效的内存位置。
在这种情况下,引用不包含零,而是无效地址。
这是崩溃的原因吗?
在这种情况下,如果我们尝试向已释放的对象发送消息,我们的程序也会崩溃,因为对象可能不是 nil 并且可能具有无效的内存地址。这就是为什么对于NON - ARC,在某些情况下,我们在发送 release 消息后也设置 obj = nil**dealloc()**
我清楚这个概念吗?
谢谢,
这样的函数会导致悬空指针吗?
int *foo () {
int a[2] = {2, 3};
int *p = NULL;
p = a;
return p;
}
Run Code Online (Sandbox Code Playgroud) 我的代码:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *p = (int *)malloc(sizeof(int));
free(p);
*p = 42;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个指针,然后我将它指向分配的空间,最后我给它分配了42.在我看来它不应该工作,它应该导致分段错误,但它的工作原理.所以为什么?
PS:我通常在Linux上用Gcc编译它
关于在C/C++中悬空指针,我有点困惑
void remove(){
Node* curr = new Node(10);
Node* pt = curr;
delete curr;
// do something here
// do other thing here
}
Run Code Online (Sandbox Code Playgroud)
我假设Node* pt在函数remove()终止之前仍然悬空指针?
终止Node* pt后我不必担心指针remove()?
我有一个简单的容器类,指向一个抽象类,我有函数来获取/设置容器类中的指针.更具体地说,这个类看起来像这样:
class Container
{
Abstract* thing;
public:
void set(Abstract &obj)
{
thing = &obj; //danger of dangling pointer
}
Abstract* get()
{
return thing;
}
};
Run Code Online (Sandbox Code Playgroud)
Abstract是一个抽象类.可以看出,存在悬挂指针的危险.我知道我可以制作一个对象的副本(新),然后指向它.但我无法创建抽象类的实例.有什么解决方案吗?
以下是更多信息:
类定义
class Abstract
{
public:
virtual void something() = 0;
};
class Base : public Abstract
{
int a;
public:
Base() {}
Base(int a) : a(a){}
virtual void something()
{
cout << "Base" << endl;
}
};
class Derived : public Base
{
int b;
public:
Derived() {}
Derived(int a, int …Run Code Online (Sandbox Code Playgroud) dangling-pointer ×10
pointers ×5
c ×4
c++ ×4
c++11 ×1
containers ×1
go ×1
objective-c ×1
realloc ×1
string ×1
unique-ptr ×1