Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-6464] Leak of enums > 32 bytes when passed to dispatch queue #666

Closed
swift-ci opened this issue Nov 23, 2017 · 6 comments
Closed

[SR-6464] Leak of enums > 32 bytes when passed to dispatch queue #666

swift-ci opened this issue Nov 23, 2017 · 6 comments

Comments

@swift-ci
Copy link

Previous ID SR-6464
Radar rdar://problem/35674625
Original Reporter oc243 (JIRA User)
Type Bug
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Compiler, libdispatch
Labels Bug, 4.1Regression, Leak
Assignee None
Priority Medium

md5: ded90b305923cb75a9e4cfd2bcf7f7e3

Issue Description:

There seems to have been a change go into swift betweenDEVELOPMENT-SNAPSHOT-2017-11-16-a and DEVELOPMENT-SNAPSHOT-2017-11-21-a such that the following code now leaks memory on Darwin and Linux:

import Dispatch
import Foundation

let syncQueue = DispatchQueue(label: "q")

enum E {
    case a(String, Character, String)
}

func foo(_ s: [String]) {
    let bar = E.a(s[0], "a", "b")
    return syncQueue.sync {
        let _ = bar
    }
}

print(MemoryLayout<E>.size)
while true {
    foo("f.f".components(separatedBy: "."))
}

It seems that memory is only leaked when the size of E is > 32 bytes.

Valgrind claims:

==12804== 1,323,178 bytes in 38,917 blocks are definitely lost in loss record 50 of 50
==12804==    at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)
==12804==    by 0x52A95F5: swift_slowAlloc (in /home/oliver/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2017-11-21-a/usr/lib/swift/linux/libswiftCore.so)
==12804==    by 0x52A962E: _swift_allocObject_ (in /home/oliver/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2017-11-21-a/usr/lib/swift/linux/libswiftCore.so)
==12804==    by 0x58082C5: function signature specialization <Arg[3] = Dead> of Swift._StringBuffer.init(capacity: Swift.Int, initialSize: Swift.Int, elementWidth: Swift.Int) -> Swift._StringBuffer (in /home/oliver/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2017-11-21-a/usr/lib/swift/linux/libFoundation.so)
==12804==    by 0x598928B: function signature specialization <Arg[0] = Owned To Guaranteed, Arg[4] = Dead> of generic specialization <Swift.Substring.UTF16View, Swift.Unicode.UTF16> of static Swift._StringBuffer.fromCodeUnits<A, B where A: Swift.Sequence, B: Swift._UnicodeEncoding, A.Element == B.CodeUnit>(A, encoding: B.Type, repairIllFormedSequences: Swift.Bool, minimumCapacity: Swift.Int) -> (Swift._StringBuffer?, hadError: Swift.Bool) (in /home/oliver/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2017-11-21-a/usr/lib/swift/linux/libFoundation.so)
==12804==    by 0x5989CF3: function signature specialization <Arg[0] = Exploded> of Foundation.NSString.substring(with: Foundation._NSRange) -> Swift.String (in /home/oliver/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2017-11-21-a/usr/lib/swift/linux/libFoundation.so)
==12804==    by 0x597D106: Foundation.NSString.components(separatedBy: Swift.String) -> [Swift.String] (in /home/oliver/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2017-11-21-a/usr/lib/swift/linux/libFoundation.so)
==12804==    by 0x5992B6D: (extension in Foundation):Swift.StringProtocol< where A.Index == Swift.String.Index>.components<A where A1: Swift.StringProtocol>(separatedBy: A1) -> [Swift.String] (in /home/oliver/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2017-11-21-a/usr/lib/swift/linux/libFoundation.so)
==12804==    by 0x10A593: main (in /home/oliver/main)
@swift-ci
Copy link
Author

Comment by Oliver Chick (JIRA)

@swift-ci create

@swift-ci
Copy link
Author

Comment by Oliver Chick (JIRA)

SIL for foo is:

Should %10 be released?

// foo(_:)
sil hidden @_T04main3fooySaySSGF : $@convention(thin) (@owned Array<String>) -> () {
// %0 // users: %8, %35, %2
bb0(%0 : $Array<String>):
%1 = global_addr @_T04main9syncQueue8Dispatch0dC0Cvp : $*DispatchQueue // user: %27
debug_value %0 : $Array<String>, let, name "s", argno 1 // id: %2
%3 = metatype $@thin E.Type
%4 = integer_literal $Builtin.Int64, 0 // user: %5
%5 = struct $Int (%4 : $Builtin.Int64) // user: %8
%6 = alloc_stack $String // users: %9, %10, %26
// function_ref specialized Array.subscript.getter
%7 = function_ref @_T0SaxSicigSS_Tg5 : $@convention(method) (Int, @guaranteed Array<String>) -> @owned String // user: %8
%8 = apply %7(%5, %0) : $@convention(method) (Int, @guaranteed Array<String>) -> @owned String // user: %9
store %8 to %6 : $*String // id: %9
%10 = load %6 : $*String // user: %23
%11 = string_literal utf16 "a" // user: %16
%12 = integer_literal $Builtin.Word, 1 // user: %16
%13 = integer_literal $Builtin.Int1, -1
%14 = metatype $@thin Character.Type // user: %16
// function_ref Character.init(_builtinExtendedGraphemeClusterLiteral:utf16CodeUnitCount:)
%15 = function_ref @_T0s9CharacterVABBp38_builtinExtendedGraphemeClusterLiteral_Bw18utf16CodeUnitCounttcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, @thin Character.Type) -> @owned Character // user: %16
%16 = apply %15(%11, %12, %14) : $@convention(method) (Builtin.RawPointer, Builtin.Word, @thin Character.Type) -> @owned Character // user: %23
%17 = string_literal utf8 "b" // user: %22
%18 = integer_literal $Builtin.Word, 1 // user: %22
%19 = integer_literal $Builtin.Int1, -1 // user: %22
%20 = metatype $@thin String.Type // user: %22
// function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
%21 = function_ref @_T0S2SBp21_builtinStringLiteral_Bw17utf8CodeUnitCountBi1_7isASCIItcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %22
%22 = apply %21(%17, %18, %19, %20) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %23
%23 = tuple (%10 : $String, %16 : $Character, %22 : $String) // user: %24
%24 = enum $E, #E.a!enumelt.1, %23 : $(String, Character, String) // users: %34, %30, %29, %25
debug_value %24 : $E, let, name "bar" // id: %25
dealloc_stack %6 : $*String // id: %26
%27 = load %1 : $*DispatchQueue // users: %32, %33
// function_ref closure #&#8203;1 in foo(_:)
%28 = function_ref @_T04main3fooySaySSGFyycfU_ : $@convention(thin) (@guaranteed E) -> () // user: %30
retain_value %24 : $E // id: %29
%30 = partial_apply [callee_guaranteed] %28(%24) : $@convention(thin) (@guaranteed E) -> () // user: %31
%31 = convert_function %30 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> () // user: %33
%32 = class_method %27 : $DispatchQueue, #DispatchQueue.sync!1 : (DispatchQueue) -> (() -> ()) -> (), $@convention(method) (@owned @noescape @callee_guaranteed () -> (), @guaranteed DispatchQueue) -> () // user: %33
%33 = apply %32(%31, %27) : $@convention(method) (@owned @noescape @callee_guaranteed () -> (), @guaranteed DispatchQueue) -> ()
release_value %24 : $E // id: %34
release_value %0 : $Array<String> // id: %35
%36 = tuple () // user: %37
return %36 : $() // id: %37
} // end sil function '_T04main3fooySaySSGF'

@swift-ci
Copy link
Author

Comment by Oliver Chick (JIRA)

This also leaks when E is a struct > 32 bytes

@aschwaighofer
Copy link
Member

What happens with the following code:

import Dispatch
import Foundation

let syncQueue = DispatchQueue(label: "q")

enum E {
    case a(String, Character, String)
}

func foo(_ s: [String]) {
    let bar = E.a(s[0], "a", "b")
    return syncQueue.sync {
        let _ = bar
    }
}

print(MemoryLayout<E>.size)
while true {
  autoreleasepool {
    foo("f.f".components(separatedBy: "."))
   }
}

@aschwaighofer
Copy link
Member

Okay, with the autorelease pool I see that DEVELOPMENT-SNAPSHOT-2017-11-16-a does not leak but later versions leak.

@aschwaighofer
Copy link
Member

Should be fixed by: apple/swift#13121

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants