私はDockerコンテナでSwift 3とZeroMQを使用しています。拡張機能を介してZeroMQ.Messageにいくつかの便利な初期化子を追加したいと思います。私が現在持っていることは、コンパイラをクラッシュさ:ZeroMQメッセージの迅速なイニシャライザでコンパイラがクラッシュする
import Foundation
import ZeroMQ
import SwiftProtobuf
extension ZeroMQ.Message {
convenience init?(string: String, encoding: String.Encoding = .utf8) {
var asData = string.data(using:encoding)!
asData.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
let unsafe = UnsafeMutableRawPointer.allocate(bytes: asData.count, alignedTo: 8)
unsafe.copyBytes(from: bytes, count: asData.count)
try? self.init(data: unsafe, size: asData.count)
}
}
convenience init?(protobuf: SwiftProtobuf.Message) {
guard let data = try? protobuf.serializedData() else {
return nil
}
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
let unsafe = UnsafeMutableRawPointer.allocate(bytes: data.count, alignedTo: 8)
unsafe.copyBytes(from: bytes, count: data.count)
try? self.init(data: unsafe, size: data.count)
}
}
}
私は、これは非常に多く、「ディープ・エンドでの中」の場合であるとして、何か間違ったことをやっていることは非常に高い可能性がある実現します。
コンパイルエラーが(可読性の利益のためにいくつかの手動行折り返しで)です:
Compile Swift Module 'src' (3 sources)
swift: /home/buildnode/disk2/workspace/oss-swift-3.1-package-linux-ubuntu-16_04/swift/
... lib/SILGen/ManagedValue.h:202:
... swift::SILValue swift::Lowering::ManagedValue::getLValueAddress() const:
Assertion `isLValue() && "This isn't an lvalue"' failed.
0 swift 0x000000000362f718
1 swift 0x000000000362fe56
2 libpthread.so.0 0x00007fd55e321390
3 libc.so.6 0x00007fd55cc87428 gsignal + 56
4 libc.so.6 0x00007fd55cc8902a abort + 362
5 libc.so.6 0x00007fd55cc7fbd7
6 libc.so.6 0x00007fd55cc7fc82
7 swift 0x0000000000b5fbfc
8 swift 0x0000000000b55ccc
9 swift 0x0000000000b9c0bd
10 swift 0x0000000000b9be2e
11 swift 0x0000000000b6af32
12 swift 0x0000000000b1f8f2
13 swift 0x0000000000b61607
14 swift 0x0000000000b572ab
15 swift 0x0000000000b5579c
16 swift 0x0000000000b5d73a
17 swift 0x0000000000b5921a
18 swift 0x0000000000b51c94
19 swift 0x0000000000bc95eb
20 swift 0x0000000000bc4cb1
21 swift 0x0000000000bc4018
22 swift 0x0000000000baea2d
23 swift 0x0000000000bacefd
24 swift 0x0000000000b57284
25 swift 0x0000000000b55ccc
26 swift 0x0000000000b9c0bd
27 swift 0x0000000000b9be2e
28 swift 0x0000000000b3720f
29 swift 0x0000000000b26dba
30 swift 0x0000000000b1f099
31 swift 0x0000000000ba28d8
32 swift 0x0000000000ba180b
33 swift 0x0000000000ba17ce
34 swift 0x0000000000b23dcb
35 swift 0x0000000000b24dbb
36 swift 0x0000000000b25415
37 swift 0x000000000047f43d
38 swift 0x000000000043b277
39 libc.so.6 0x00007fd55cc72830 __libc_start_main + 240
40 swift 0x00000000004386b9
Stack dump:
0. Program arguments: /usr/bin/swift -frontend ...
1. While silgen constructor initializer SIL function @_TFE3srcC6ZeroMQ7MessagecfT6stringSS8encodingVE10FoundationSS8Encoding_GSqS1__
for 'init' at /app/Simple/Sources/extensions.swift:24:17
2. While silgen closureexpr SIL function @_TFFE3srcC6ZeroMQ7MessagecFT6stringSS8encodingVE10FoundationSS8Encoding_GSqS1__U_FGSPVs5UInt8_T_
for expression at [/app/Simple/Sources/extensions.swift:27:33 - line:31:9]
RangeText="{ (bytes: UnsafePointer<UInt8>) in
let unsafe = UnsafeMutableRawPointer.allocate(bytes: asData.count, alignedTo: 8)
unsafe.copyBytes(from: bytes, count: asData!.count)
try? self.init(data: unsafe, size: asData!.count)
}"
<unknown>:0: error: unable to execute command: Aborted
同様のコードが、Factory Methodパターンを、次のことは結構ですので、私はこの問題は、使用中であることを信じていますtry?
の指定された初期化子への呼び出し。
編集: 末尾の閉鎖のうち、self.init(...)
を引くための代替的アプローチ:
convenience init?(string: String, encoding: String.Encoding = .utf8) {
guard let data = string.data(using:encoding) else {
return nil
}
let unsafe = UnsafeMutableRawPointer.allocate(bytes: data.count, alignedTo: 8)
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
unsafe.copyBytes(from: bytes, count: data.count)
}
do {
try self.init(data: unsafe, size: data.count)
} catch {
unsafe.deallocate(bytes: data.count, alignedTo: 8)
}
}
上記は、私は理解していないエラーが得られます。
交換extensions.swift:41:17: error: 'self' used inside 'catch' block reachable from self.init call
convenience init?(string: String, encoding: String.Encoding = .utf8) {
do { ... } catch { ... }
は1つのライナーでコンパイラを満たしますが、初期化子がスローした場合にバッファをリークします(ZeroMQは成功のメモリを所有します)。ケース:
try? self.init(data: unsafe, size: data.count)