我最近问了一个关于在Perl中覆盖对象和内存管理的问题.我收到的一个答案告诉我,我最近写的脚本可能有问题.
我有一个脚本,有一些非常复杂的数据结构,有许多parent->child / child->parent关系.这也意味着有许多对象具有循环引用.根据这个答案,循环引用可以"欺骗"Perl的引用计数机制,如果没有正确处理它们会导致内存泄漏.
循环引用的示例:
+-----------------------------------------------------+
| |
+-->+============+ +==========+ |
[ Reference ----->[ Blessed ] |
$parent -->+============+ [ Hash ] |
[ ] +==========+ |
[ children --->[ Array ] |
[ ] [ ] |
+==========+ [ 0: ---------+ |
[ ] | |
+==========+ | |
| |
+--------------------------------------------------+ |
| |
+-->+============+ +==========+ |
[ Reference ----->[ Blessed ] |
$child --->+============+ [ Hash ] |
[ ] | …Run Code Online (Sandbox Code Playgroud) 考虑这些枚举声明:
enum Color {
RED(Shape.CIRCLE),
GREEN(Shape.TRIANGLE),
BLUE(Shape.SQUARE);
private final Shape shape;
Color(Shape shape) {
this.shape = shape;
}
Shape getShape() {
return shape;
}
}
enum Shape {
CIRCLE(Color.RED),
TRIANGLE(Color.GREEN),
SQUARE(Color.BLUE);
private final Color color;
Shape(Color color) {
this.color = color;
}
Color getColor() {
return color;
}
}
Run Code Online (Sandbox Code Playgroud)
枚举字段之间存在循环依赖关系。没有编译器警告(使用 Java 8)。
然而,所有这些测试都将在第二行失败:
@Test
public void testRedAndCircle() {
assertThat(Color.RED.getShape()).isNotNull();
assertThat(Shape.CIRCLE.getColor()).isNotNull(); // fails
}
@Test
public void testCircleAndRed() {
assertThat(Shape.CIRCLE.getColor()).isNotNull();
assertThat(Color.RED.getShape()).isNotNull(); // fails
}
@Test
public void testGreenAndTriangle() {
assertThat(Color.GREEN.getShape()).isNotNull();
assertThat(Shape.TRIANGLE.getColor()).isNotNull(); …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用循环引用boost::shared_ptr,并设计了以下示例:
class A{ // Trivial class
public:
i32 i;
A(){}
A(i32 a):i(a){}
~A(){
cout<<"~A : "<<i<<endl;
}
};
shared_ptr<A> changeI(shared_ptr<A> s){
s->i++;
cout<<s.use_count()<<'\n';
return s;
}
int main() {
shared_ptr<A> p1 = make_shared<A>(3);
shared_ptr<A> p2 = p1;
shared_ptr<A> p3 = p2;
shared_ptr<A> p4 = p3;
p1 = p4; // 1) 1st cyclic ref.
cout<<p1.use_count()<<'\n';
p1 = changeI(p4); // 2) 2nd cyclic ref.
cout<<p1.use_count()<<'\n';
// putchar('\n');
cout<<endl;
}
Run Code Online (Sandbox Code Playgroud)
哪个输出
4
5
4
~A : 4
Run Code Online (Sandbox Code Playgroud)
是不是我误解了所提到的循环引用boost::shared_ptr?因为,我预计间接引用的不同输出思维p1 …
我有一个多模块项目,如下所示:
module2中的pom.xml依赖于module1.
当我运行mvn clean编译时,我收到以下错误:
反应堆中的项目包含循环参考.
这是我在module1中的依赖项:
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.48</version>
</dependency>
</dependencies>
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚为什么它说有一个循环引用.即使我做了mvn依赖:在module1上的树,我得到以下内容:
[INFO] +- log4j:log4j:jar:1.2.14:compile
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.6.1:compile
[INFO] | \- org.slf4j:slf4j-api:jar:1.6.1:compile
[INFO] +- com.jcraft:jsch:jar:0.1.48:compile
[INFO] \- junit:junit:jar:4.8.2:test
Run Code Online (Sandbox Code Playgroud)
在我看来,在module1中没有对module2的任何引用.那么循环引用来自何处?
编辑:以下是调试日志:
+ Error stacktraces are turned on.
Apache Maven 2.2.1 (r801777; 2009-08-06 15:16:01-0400)
Java version: 1.6.0_31
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 7" version: "6.1" arch: "amd64" Family: "windows"
[INFO] Scanning …Run Code Online (Sandbox Code Playgroud) public struct Unit
{
Unit u;
}
Run Code Online (Sandbox Code Playgroud)
原因:
类型为"单位"的结构成员"Unit.u"会在结构布局中生成一个循环.
但
public class Unit
{
Unit u;
}
Run Code Online (Sandbox Code Playgroud)
编译.我理解我认为的问题.引用Unit对象时将形成无限循环,因为它必须初始化另一个成员Unit,依此类推.但是为什么编译器只是为了限制问题structs呢?这个问题也不存在class吗?我错过了什么吗?
试图找到一个好的和正确的模式来处理Python中的循环模块依赖.通常,解决方案是将其删除(通过重构); 但是,在这种特殊情况下,我们真的希望拥有需要循环导入的功能.
编辑:根据下面的答案,这种问题的通常攻角是重构.但是,为了这个问题,假设这不是一个选项(无论出于何种原因).
问题:
该logging模块要求configuration模块提供一些配置数据.但是,对于某些configuration功能,我真的想使用logging模块中定义的自定义日志记录功能.显然,导入logging模块configuration会引发错误.
我们可以想到的可能的解决方案:
不要这样做.正如我之前所说,这不是一个好的选择,除非所有其他可能性都是丑陋和糟糕的.
猴子补丁模块.这听起来不是太糟糕了:在加载logging模块动态进入configuration 后的初始导入,和之前的任何职能被实际使用.这意味着定义全局的每模块变量.
依赖注入.我已阅读并尝试依赖注入替代方案(特别是在Java Enterprise空间中),它们消除了一些令人头痛的问题; 然而,它们可能太复杂而无法使用和管理,这是我们想要避免的.但是,我不知道Python中的全景图是怎样的.
什么是启用此功能的好方法?
非常感谢!
python module cyclic-reference importerror cyclic-dependency
我来自OO背景(C#,javascript),而Scala是我第一次涉足FP.
由于我的背景,我无法很好地实现适合我的域问题的域模型,并且还符合FP的良好实践,例如代码中的最小可变性.
首先,简要描述我现在的域名问题.
Event, Tournament, User, and TeamTeams 由...组成 UsersTeams并Users可以参加Tournaments这发生在一个EventEvents由Users和组成TournamentsTeams和Users谁竞争,跨越Tournaments和Events将是一大特色.鉴于问题的这种描述,我对域的最初想法是创建对象,其中双向循环关系是常态 - 类似于图形.我的想法是,能够访问任何给定对象的所有关联对象将为我提供最简单的路径,为我的数据编程视图,并操纵它.
case class User(
email: String,
teams: List[TeamUser],
events: List[EventUser],
tournaments: List[TournamentUser]) {
}
case class TournamentUser(
tournament: Tournament,
user: User,
isPresent: Boolean){
}
case class Tournament(
game: Game,
event: Event,
users: List[TournamentUser],
teams: List[TournamentTeam]) {
}
Run Code Online (Sandbox Code Playgroud)
然而,随着我进一步深入FP最佳实践,我发现我的思维过程与FP原则不相容.循环引用是不受欢迎的,似乎几乎不可能与不可变对象.
鉴于此,我现在正在努力解决如何重构我的域以满足良好FP的要求,同时仍然保持域中"真实世界对象"的常识组织.
我考虑过的一些选择
functional-programming scala immutability domain-model cyclic-reference
我的休眠域模型中有循环引用导致 Betwixt 失败。我不想改变我的域模型。
如何更改 Betwixt 以忽略循环引用?
带有循环引用的"Fun":
假设我有一个表ELEMENTS,它包含一个由父ID建模的元素层次结构.
对于root,父ID字段为空.
所有其他记录都具有ID父元素的(autosequenced)主键()的非null父id .
例如,使用
SELECT *
FROM Elements
WHERE FATHER_ID not in (SELECT ID FROM Elements)
Run Code Online (Sandbox Code Playgroud)
我可以找到所有具有无效父引用的元素(FATHER_ID不是外键,我们假设在这个例子中).
但是,我怎样才能找到具有有效父引用BUT的元素,其父引用链不会以根结尾?我认为这只能发生在循环引用上,例如A是B的父亲,但B也是A的父亲.这样的"子树"没有链接到根,因此不是主树的一部分.我想找到这样的子树.
当然,我正在寻找一个查询来提供那些导致循环引用的元素,无论引用链可能有多长.
这可能在SQL中,还是需要迭代解决方案?
我正在尝试在Rust中编写一个容器结构,其中元素也存储对包含容器的引用,以便它们可以在其上调用方法.据我所知,我需要做到这一点Rc<RefCell<T>>.它是否正确?
到目前为止,我有以下内容:
struct Container {
elems: ~[~Element]
}
impl Container {
pub fn poke(&mut self) {
println!("Got poked.");
}
}
struct Element {
datum: int,
container: Weak<RefCell<Container>>
}
impl Element {
pub fn poke_container(&mut self) {
let c1 = self.container.upgrade().unwrap(); // Option<Rc>
let mut c2 = c1.borrow().borrow_mut(); // &RefCell
c2.get().poke();
// self.container.upgrade().unwrap().borrow().borrow_mut().get().poke();
// -> Error: Borrowed value does not live long enough * 2
}
}
fn main() {
let container = Rc::new(RefCell::new(Container{ elems: ~[] }));
let mut …Run Code Online (Sandbox Code Playgroud) cyclic-reference ×10
java ×2
betwixt ×1
c# ×1
c++ ×1
class ×1
domain-model ×1
enums ×1
immutability ×1
importerror ×1
jls ×1
maven ×1
memory-leaks ×1
module ×1
multi-module ×1
oop ×1
oracle ×1
perl ×1
python ×1
reference ×1
rust ×1
scala ×1
shared-ptr ×1
sql ×1
struct ×1
weak-ptr ×1