标签: object-lifetime

这个object-lifetime-extends-closure是一个C#编译器错误吗?

当我在C#编译器遇到一些非常奇怪的代码时,我正在回答关于闭包(合法地)延长对象生命周期的可能性的问题(如果重要的话,那就是4.0).

我能找到的最短的repro如下:

  1. 在调用包含类型的静态方法时创建一个捕获局部的lambda .
  2. 将生成的委托引用分配给包含对象的实例字段.

结果:编译器创建一个闭包对象,该对象引用创建lambda的对象,当它没有理由时 - 委托的"内部"目标是静态方法,并且lambda-creation-object的实例成员不需要在委托执行时被(并且没有)触摸.实际上,编译器的行为就像程序员this无缘无故地捕获的那样.

class Foo
{
    private Action _field;

    public void InstanceMethod()
    {
        var capturedVariable = Math.Pow(42, 1);

        _field = () => StaticMethod(capturedVariable);
    }

    private static void StaticMethod(double arg) { }
}
Run Code Online (Sandbox Code Playgroud)

发布版本生成的代码(反编译为'simpler'C#)如下所示:

public void InstanceMethod()
{

    <>c__DisplayClass1 CS$<>8__locals2 = new <>c__DisplayClass1();

    CS$<>8__locals2.<>4__this = this; // What's this doing here?

    CS$<>8__locals2.capturedVariable = Math.Pow(42.0, 1.0);
    this._field = new Action(CS$<>8__locals2.<InstanceMethod>b__0);
}

[CompilerGenerated]
private sealed class …
Run Code Online (Sandbox Code Playgroud)

c# lambda closures memory-leaks object-lifetime

136
推荐指数
2
解决办法
3811
查看次数

C++中的对象破坏

什么时候C++中的对象被破坏了,这意味着什么?我是否必须手动销毁它们,因为没有垃圾收集器?例外是如何发挥作用的?

(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)

c++ destructor exception c++-faq object-lifetime

67
推荐指数
2
解决办法
2万
查看次数

为什么对于非TriviallyCopyable的对象,未定义std :: memcpy的行为?

来自http://en.cppreference.com/w/cpp/string/byte/memcpy:

如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为未定义.

在我的工作中,我们使用std::memcpy了很长时间来按比例交换不是TriviallyCopyable的对象:

void swapMemory(Entity* ePtr1, Entity* ePtr2)
{
   static const int size = sizeof(Entity); 
   char swapBuffer[size];

   memcpy(swapBuffer, ePtr1, size);
   memcpy(ePtr1, ePtr2, size);
   memcpy(ePtr2, swapBuffer, size);
}
Run Code Online (Sandbox Code Playgroud)

从来没有任何问题.

我理解滥用std::memcpy非TriviallyCopyable对象并导致下游的未定义行为是微不足道的.但是,我的问题是:

std::memcpy当与非TriviallyCopyable对象一起使用时,为什么它本身的行为是未定义的?为什么标准认为有必要指定?

UPDATE

http://en.cppreference.com/w/cpp/string/byte/memcpy的内容已经过修改,以回应这篇文章和帖子的答案.目前的描述说:

如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为是未定义的,除非程序不依赖于目标对象(不运行memcpy)的析构函数的效果和生命周期目标对象(已结束,但未开始memcpy)由其他一些方法启动,例如placement-new.

PS

@Cubbi的评论:

@RSahu如果有东西保证UB下游,它会使整个程序不确定.但我同意在这种情况下似乎可以绕过UB并相应​​地修改cppreference.

c++ memcpy object-lifetime language-lawyer c++11

67
推荐指数
5
解决办法
5355
查看次数

在C++函数中"返回"的确切时刻

这似乎是一个愚蠢的问题,但是return xxx;在一个明确定义的函数中"执行" 的确切时刻?

请参阅以下示例以了解我的意思(现在直播):

#include <iostream>
#include <string>
#include <utility>

//changes the value of the underlying buffer
//when destructed
class Writer{
public:
    std::string &s;
    Writer(std::string &s_):s(s_){}
    ~Writer(){
        s+="B";
    }
};

std::string make_string_ok(){
    std::string res("A");
    Writer w(res);
    return res;
}


int main() {
    std::cout<<make_string_ok()<<std::endl;
} 
Run Code Online (Sandbox Code Playgroud)

我天真地期待发生的事情make_string_ok被称为:

  1. 构造函数res被调用(价值res就是"A")
  2. w调用构造函数
  3. return res被执行.应该返回res的当前值(通过复制当前值res),即"A".
  4. w被称为析构函数,值res变为"AB".
  5. 析构res函数被称为.

所以我希望"A"结果,但"AB" …

c++ object-lifetime language-lawyer copy-elision c++17

67
推荐指数
3
解决办法
4121
查看次数

AppDomain和MarshalByRefObject的生命周期:如何避免RemotingException?

当MarshalByRef对象从AppDomain(1)传递到另一个(2)时,如果你在第二个AppDomain(2)中调用方法之前等待6分钟,你将得到一个RemotingException:

System.Runtime.Remoting.RemotingException:对象[...]已断开连接或在服务器上不存在.

有关此问题的一些文档:

如果我错了,请纠正我:如果InitializeLifetimeService返回null,那么当AppDomain 2被卸载时,该对象只能在AppDomain 1中收集,即使收集了代理?

有没有办法禁用生命周期并保持代理(在AppDomain 2中)和对象(在AppDomain1中)保持活动状态,直到代理完成为止?也许与ISponsor ......?

.net c# remoting appdomain object-lifetime

56
推荐指数
4
解决办法
3万
查看次数

破坏析构函数异常的返回值

我有以下代码:

#include <stdexcept>
#include <iostream>

struct ok {
    int _n;
    ok(int n) : _n(n) { std::cerr << "OK" << n << " born" << std::endl; }
    ~ok() {  std::cerr << "OK" << _n << " gone" << std::endl; }
};

struct problematic {
    ~problematic() noexcept(false) { throw std::logic_error("d-tor exception"); }
};

ok boo() {
    ok ok1{1};
    problematic p;
    ok ok2{2};
    return ok{3}; // Only constructor is called...
}

int main(int argc, char **argv) {
    try {boo();} catch(...) {}
}
Run Code Online (Sandbox Code Playgroud)

我看到他没有调用ok …

c++ destructor exception object-lifetime c++14

38
推荐指数
1
解决办法
1159
查看次数

与函数指针转换相关的lambda对象的生命周期

根据这个答案,我现在想知道lambda的生命周期是什么规则,以及与自动转换创建的函数指针的生命周期有什么关系.关于lambda的生命周期有几个问题(例如这里这里),在这种情况下,答案是"它们的行为与你自己编写完整的仿函数对象完全一样",但是它们都没有解决转换为函数指针的问题.特殊情况.

我把这个小小的工作实例放在一起,说明了我的担忧:

#include <iostream>

typedef int (*func_t)(int);

// first case
func_t retFun1() {
  static auto lambda = [](int) { return 1; };
  // automatically converted to func_t
  return lambda;
}

// second case
func_t retFun2() {
  // no static
  auto lambda = [](int) { return 2; };
  // automatically converted to func_t and 
  // the local variable lambda reaches the end of its life
  return lambda;
}

int main() {
  const int a = …
Run Code Online (Sandbox Code Playgroud)

c++ lambda object-lifetime c++11

37
推荐指数
1
解决办法
2558
查看次数

从基类构造函数调用纯虚函数

我有一个包含纯虚函数的基类MyBase:

void PrintStartMessage() = 0

我希望每个派生类在它们的构造函数中调用它

然后我把它放在基类(MyBase)构造函数中

 class MyBase
 {
 public:

      virtual void PrintStartMessage() =0;
      MyBase()
      {
           PrintStartMessage();
      }

 };

 class Derived:public MyBase
 {     

 public:
      void  PrintStartMessage(){

      }
 };

void main()
 {
      Derived derived;
 }
Run Code Online (Sandbox Code Playgroud)

但我收到链接器错误.

 this is error message : 

 1>------ Build started: Project: s1, Configuration: Debug Win32 ------
 1>Compiling...
 1>s1.cpp
 1>Linking...
 1>s1.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall MyBase::PrintStartMessage(void)" (?PrintStartMessage@MyBase@@UAEXXZ) referenced in function "public: __thiscall MyBase::MyBase(void)" (??0MyBase@@QAE@XZ)
 1>C:\Users\Shmuelian\Documents\Visual Studio 2008\Projects\s1\Debug\s1.exe : fatal …
Run Code Online (Sandbox Code Playgroud)

c++ constructor abstract-class pure-virtual object-lifetime

35
推荐指数
4
解决办法
3万
查看次数

破坏函数参数的顺序是什么?

如果某些函数f带有参数p_1,...,p_n类型T_1,...,T_n分别用参数调用a_1,......,a_n并且它的正文抛出异常,则完成或返回,参数被破坏的顺序是什么?为什么?如果可能,请提供标准参考.

编辑:我实际上想询问函数"参数",但是由于TC和Columbo设法清除了我的困惑,我将这个问题留下来讨论参数并询问一个关于参数的新单独问题.有关区别,请参阅有关此问题的评论.

c++ arguments function object-lifetime language-lawyer

35
推荐指数
3
解决办法
1923
查看次数

大括号的类型如何影响 C++ 中的对象生命周期?

我的一个朋友给我看了一个 C++20 程序:

#include <iostream>

struct A
{
    A() {std::cout << "A()\n";}
    ~A() {std::cout << "~A()\n";}
};

struct B
{
    const A &a;
};

int main()
{
    B x({});
    std::cout << "---\n";
    B y{{}};
    std::cout << "---\n";
    B z{A{}};
    std::cout << "---\n";
}
Run Code Online (Sandbox Code Playgroud)

在 GCC 中,它打印:

A()
~A()
---
A()
---
A()
---
~A()
~A()
Run Code Online (Sandbox Code Playgroud)

https://gcc.godbolt.org/z/ce3M3dPeo

因此,A在 y 和 z 情况下,的寿命会延长。

在 Visual Studio 中,结果是不同的:

A()
~A()
---
A()
---
A()
~A()
---
~A()
Run Code Online (Sandbox Code Playgroud)

所以A只有在 y …

c++ initialization object-lifetime temporary-objects c++20

33
推荐指数
1
解决办法
1115
查看次数