Unsafe Dangling pointer

Hi, I am new to programming, I got work to remove warnings and errors thrown by swiftLint. I have resolved most of the warnings but I am stuck at one place.
let ptrOptions = UnsafeMutablePointer(&Options)

Where Options is a struture.
it is saying that it might result in a dangling pointer. How I can remove thsi?

the full error message is

warning: initialization of 'UnsafeMutablePointer<Options>' results in a dangling pointer
let ptrOptions = UnsafeMutablePointer(&options)
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: implicit argument conversion from 'Options' to 'UnsafeMutablePointer<Options>' produces a pointer valid only for the duration of the call to 'init(_:)'
let ptrOptions = UnsafeMutablePointer(&options)
                                      ^~~~~~~~
note: use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope
let ptrOptions = UnsafeMutablePointer(&options)
                                      ^

it suggest a solution, which is withUnsafeMutablePointer

withUnsafeMutableBytes(of: &options) { ptrOptions in
    ...
}

be aware that the ptrOptions is valid only inside the closure.

@cukr i ran into same issue but in my case pointer(ptrOptions) should be variable instead of let constant any idea how i resolve this issue ?

Let's back up just a little bit; what are you actually going to do with the pointer you're trying to create?

2 Likes

@scanon Thank you for replying , i have to pass that pointer to the function .

i have to pass that pointer to the function.

It would help us to help you if you provided a little more info on your goals. Can you post a small snippet that illustrates the problem you’re having?

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

2 Likes

@eskimo thank you for responding
Code snippet

withUnsafeMutableBytes(of: &optionArray) { (ptrOption) -> Void in
                do {
                var return = try lib.function(v1: &v1.access, v2: &ptrOption, v3: &v3, v4: v4.count)
            
                }catch{
                    print("Error")
                }
            }

Compiler is throwing dangling pointer warning , i want to remove that dangling pointer warning.
i have to pass pointer (ptrOption) to function lib.function
variable optionArray is array of C obj

Any other way i can remove dangling pointer ?

What @eskimo and I are trying to get at is "what is lib.function, specifically?". The correct solution depends on that information. For instance, suppose lib.function were something like the following:

lib.h:
----
struct resultType {
  int count;
  option *options;
}

struct resultType function(int optionCount, option *options) {
  return (resultType){ optionCount, options }
}

In a case like this, you wouldn't be able to return (or use) the result outside of the closure scoped to withUnsafeMutableBytes, because the pointer options contained in the C struct would not be valid outside of that scope.

1 Like

Also, if you want more general background on this, I wrote up my experience in The Peril of the Ampersand.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

3 Likes

A harrowing tale of misery and woe, set in an ancient land.

1 Like

Thanks @eskimo , i am able to remove some dangling pointer warning after reading about Ampersand . :+1: Thank you for sharing link of The Peril of the Ampersand

lib -> lib is a struct in swift module
function -> is a method/function inside swift module structure (lib)
function does the following task :

  1. Open .dylib file of Clibaray
  2. Load Sym of the function
  3. Call C library function
  4. Return Response of that function
var optionvar = Options()
var optionArray = [optionvar] //Trying to create array 
var return = try lib.function(v1: &v1.access, v2: &optionArray, v3: &v3, v4: v4.count)

When i am trying to pass optionArray it is throwing error .
Cannot convert [optionvar] to UnsafeMutablePointer<[Options]>

It’s hard to say what’s going on here without more details. However, I took the code you posted and turned it into a minimal example and that works just fine:

// main.swift

var optionsArray = [Options](repeating: Options(), count: 5)
let result = gLibrary.function(&optionsArray, optionsArray.count)
optionsArray.removeLast(optionsArray.count - result)
print(optionsArray.map { $0.flag })
// printed: [100, 118, 102]

// CCode.h

#include <stddef.h>

struct Options {
    int flag;
};

struct Library {
    size_t (*function)(struct Options * options, size_t optionsCount);
};

extern struct Library gLibrary;

// CCode.c

#include "CCode.h"

static size_t myFunction(struct Options * options, size_t optionsCount) {
    static int flags[] = { 'd', 'v', 'f' };
    size_t i;
    for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
        struct Options o;
        o.flag = flags[i];
        if (i < optionsCount) {
            options[i] = o;
        }
    }
    return i;
}

struct Library gLibrary = {
    .function = myFunction
};

If the above example doesn’t help, I need to you reduce the problematic case to something like the above, where I can see all of the code involved.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

1 Like