回答編集履歴

1

追記への回答

2019/09/06 09:33

投稿

yuki23
yuki23

スコア1448

test CHANGED
@@ -13,3 +13,97 @@
13
13
 
14
14
 
15
15
  また、運が良ければ、静的解析ツールや valgrind などのメモリ解析ツールを使うと手がかりが得られる場合もあります。
16
+
17
+
18
+
19
+ ---
20
+
21
+ 追記へ
22
+
23
+
24
+
25
+ 要するにこういうことでしょうか?
26
+
27
+
28
+
29
+ ```
30
+
31
+ SomeObject::slotA()
32
+
33
+ {
34
+
35
+ ……前の処理……
36
+
37
+ ループ {
38
+
39
+ QEventLoop loop;
40
+
41
+ connect(1秒の単発タイマー → loop の quit);
42
+
43
+ loop.exec();
44
+
45
+
46
+
47
+ ……次の処理…… ← ここで発生
48
+
49
+ }
50
+
51
+ }
52
+
53
+ ```
54
+
55
+
56
+
57
+ 「QEventLoop を使ってスリープする」というのは間違った使い方です。
58
+
59
+ QEventLoop を呼ぶと、スロットが実行中にも関わらず、同じスレッドに属するあらゆるオブジェクトのあらゆるスロットを呼ぶことが可能になってしまいます。この状況で SomeObject が delete されないように厳密に管理することは極めて困難です。「気をつけて設計すればいい」という問題ではありません。
60
+
61
+
62
+
63
+ 基本的に QEventLoop をスロットの中で呼ぶのはNGだとお考え下さい。
64
+
65
+ もしチームで開発しているのでしたら、コーディング規約で禁止することをお勧めします。
66
+
67
+
68
+
69
+ 正しくは、例えば次のようにします。
70
+
71
+
72
+
73
+ ```
74
+
75
+ SomeObject::slotA()
76
+
77
+ {
78
+
79
+ ……前の処理……
80
+
81
+ connect(1秒の単発タイマー → slotB);
82
+
83
+ return;
84
+
85
+ }
86
+
87
+
88
+
89
+ SomeObject::slotB()
90
+
91
+ {
92
+
93
+ ……次の処理……
94
+
95
+ if (必要であれば) {
96
+
97
+ connect(1秒の単発タイマー → slotB);
98
+
99
+ }
100
+
101
+ }
102
+
103
+ ```
104
+
105
+
106
+
107
+ このようにすればタイマーで待っている最中に this が delete されても問題ありません(少なくともセグフォが発生しないという点については)
108
+
109
+ なお、Qt 5 以降なので、スロットの代わりにラムダを使うこともできます。「ラムダとは何か?」から説明するのは大変なので、興味がお有りであればご自分でお調べ下さい。