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-3231] Generated C string doesn't survive until called C function returns #45819
Comments
The situation you've described should behave as expected, so I'm guessing there's something more complicated going on. Can you attach a full reproducing test case? |
Comment by Markus Hanauska (JIRA) I cannot reproduce that in a simple stripped down test case but I can reproduce that 100% in our application. Dangling pointers is something you can hardly ever reproduce with simple test cases as in a single threaded app I can usually access freed memory just fine as long as I perform no alloc operation that might wipe it (rarely this will fail in a very simple app). What I don't understand is that I cannot even find the allocation of the C string when I run the project in Instruments. I added this line of code So I currently have no way to find out when this memory is created, by whom it is created and when and by whom it is freed again. I tried malloc history but when I query that address, I also just get an error and no history. I tried setting watchpoints on the string memory, no success either. The only thing I've been able to find out so far is that between the last Swift line and the first C line, there's a call to |
Comment by Markus Hanauska (JIRA) By the way, I ended up to write code like this: let tempString = optString as NSString?
let data = MyFunction(tempString?.utf8String) And this codes works flawlessly and exactly as expected (also passes all instrument/guard malloc tests). |
Are you able to attach the code that contains the call? I'm pretty sure that'll help figure out what's going on. |
Comment by Markus Hanauska (JIRA)
Only if I clean it up first, which will be quite a bit of work; but I'm giving my best. Let me just share some more details that could all play a role:
|
Ooh, I wonder if the optional chaining is messing it up. What happens if you break that out into a separate assignment into a |
Comment by Markus Hanauska (JIRA) @belkadan You could be on the right track here. While this code fails every time let optString = someObj.someString
let data = MyFunction(optString) this code so far has been working every time: guard let optString = someObj.someString else { return }
let data = MyFunction(optString) Just that let data: // appropriate-type
if let string = someObj.someString {
data = MyFunction(string)
} else {
data = MyFunction(nil)
} but I have other C functions that take up to eight parameters of that kind and this solution would not work there. I was considering writing it like that but that doesn't work at all: let data = MyFunction( (optString != nil ? optString! : nil) ) Calling the function like that causes the first character of the string to be already corrupted when the C function enters. |
@swift-ci create |
I think John fixed this in #9033 ! If you want, you can test it by downloading a development snapshot from swift.org. |
Comment by Matt Deckard (JIRA) If [SR-4249] is truly a duplicate of this issue, then as far as I can tell, it had already been fixed as of Xcode 8.3.2. EDIT: Well actually I can't even reproduce it in 8.2.1 now, so I don't know what is going on... |
This was definitely still broken in 8.3.2. It's the optional that throws things off. |
Additional Detail from JIRA
md5: afb3f0f08a5c97423951a93c429a0a5c
is duplicated by:
relates to:
Issue Description:
I have a C function that expects an optional string as argument (among other parameters, but let's ignore these for a moment). The C declaration looks like this:
and for Swift it looks like this:
What I'm doing now, I'm trying to feed a Swift string, imagine that code:
When I break into
MyFunction
, the string looks perfectly okay at the top of it but when it then calls another C function, the string is junk on return. I ran the app with guard malloc enabled and this even crashes whenMyFunction
is trying to use that string, so the string memory seems to have been released already at that moment, which would also explain why it becomes corrupted.I do understand that the automatic generated C string has a very limited lifespan, so I don't expect it to stay alive beyond the call of
MyFunction
, because how would its memory be managed to not leak otherwise? But in my case it doesn't even seem to stay alive whileMyFunction
is still running and that's something I don't understand.MyFunction
adds the string to a C array of strings, like this:and a reference to
strings
is passed around but that really shouldn't play a role. As long as the C string stays alive untilMyFunction
returns, everything should be okay, as after return nobody holds or uses a reference tooptString
any longer (its data will have been copied to internal buffer already).The text was updated successfully, but these errors were encountered: