了解几秒钟后导致信号11(SIGSEGV),代码1(SEGV_MAPERR)错误的Android问题

问题描述 投票:0回答:1

我正在运行传感器和位置服务,数据将传递到TraceManager文件,在该文件中进行处理,然后传递到TraceCWrapper以映射到共享的C库.so,看来传感器和位置数据很好并在TraceManager中接收,然后将其传递到TraceCWrapper,但是该应用在几秒钟后崩溃,我得到的唯一错误行是:

A / libc:致命信号11(SIGSEGV),代码1(SEGV_MAPERR),在tid 29938(AsyncTask#1),pid 29870(pp.traceandroid)中的故障加法器0x8]



public class TraceManager extends AppCompatActivity {

    private String TAG = "TraceManager";
    private int phoneAngle = 0;
    private double initialStepCalibrationOffset;
    private int initialPointingAngleDeg = 0;
    private int initialAlignmentMode = 0;
    private int startingFloorID = 0;
    private LatLng startingLatLong;
    private double startingAccuracy = 1.0;
    private Context context;
    private boolean isMagConsistentAtInit = false;
    private boolean isMagValid = true;
    private Timer callBackTimer;
    private String[] contentsStatic;
    private String[] contentsDynamic;
    private boolean isRunning = false;
    private TraceCWrapper traceCWrapper = new TraceCWrapper();
    Handler callbackHandler = new Handler();
    Runnable callbackRunnable;

    //internal use only
    private boolean _traceCDontActuallyUse;

    // The interval, in seconds, for providing trace updates.
    public ObservableDouble updateCallbackInterval = new ObservableDouble(0){
        @Override
        public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
            if(isRunning){
                stopCallbackTimer();
                startCallbackTimer();
            }

            super.addOnPropertyChangedCallback(callback);
        }
    };

    private double updateCallBackIntervalValue = updateCallbackInterval.get();

    /// A Boolean value
    public ObservableBoolean allowsBackgroundExecution = new ObservableBoolean(false){
        @Override
        public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
            if(isRunning){
                stopUpdatingTrace();
                startUpdatingTrace();
            }
            super.addOnPropertyChangedCallback(callback);
        }
    };

    private boolean allowsBackgroundExecutionValue = allowsBackgroundExecution.get();


    public TraceManager(Context context){
        this.context=context;
    }


    public TraceManager(){

    }

    public void initialiseTrace(String[] mapFloors,
                                String[] initialDynamicMaps,
                                int phoneRelativeToBodyDegree, //this comes from onboarding?
                                double updateCallBackIntervalValue,
                                boolean allowsBackgroundExecutionValue,
                                double initialStepCalibrationOffset, //standard
                                String[] iBeaconUUIDs,
                                int startingFloorID,
                                LatLng startingLatLong, //this is form the starting node
                                double startingAccuracy, //
                                boolean _traceCDontActuallyUse,
                                int phoneOrientation,
                                int phoneOrientationUse,
                                boolean magntometerValid
                                ){
        this.contentsStatic = mapFloors;
        this.contentsDynamic = initialDynamicMaps;
        this.phoneAngle = phoneRelativeToBodyDegree;
        this.initialStepCalibrationOffset = initialStepCalibrationOffset;
        this.updateCallbackInterval = updateCallbackInterval;
        this.allowsBackgroundExecution = allowsBackgroundExecution;
        this.isMagValid = magntometerValid;
        if(!(iBeaconUUIDs.length <=0)){
            LocationProvider.arrayOfUUIDsToDetect = iBeaconUUIDs;
        }else{
            Log.i(TAG, "TraceManager.init: ignoring ibeaconUIDs, because it is empty. Default used");
        };

        this.startingFloorID = startingFloorID;
        this.startingLatLong = startingLatLong;
        this.startingAccuracy = startingAccuracy;
        this.initialPointingAngleDeg = phoneOrientation;
        this.initialAlignmentMode = phoneOrientationUse;

        //internal use only
        this._traceCDontActuallyUse = _traceCDontActuallyUse;
    }

//Functions
/// Broadcast Receiver to get readings from MotionProvider/service

    public void startUpdatingSensors(){
        //Start sensor service
        Intent startService = new Intent(TraceManager.this, SensorService.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(startService);
        } else {
            startService(startService);
        }

    }

    /// Starts the generation of trace updates.

    public void startUpdatingTrace(){
        //Start Sensors
        //startUpdatingSensors();

        //register for sensorBroadcast
        BroadcastReceiver sensorReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Log.d(TAG, "imu Received");
                TCIMUEvent tcimuEvent = (TCIMUEvent) intent.getSerializableExtra("imu");
                traceCWrapper.provideDeviceMotion(tcimuEvent, 1, 90, RotationMode.PortraitYUp);
            }
        };
        LocalBroadcastManager.getInstance(context).registerReceiver(
                sensorReceiver, new IntentFilter("imuCreated")
        );

        //register for locationBroadcast
        //register for sensorBroadcast
        BroadcastReceiver locationReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Log.d(TAG, "location Received");
                TCLocationEvent tcLocationEvent = (TCLocationEvent) intent.getSerializableExtra("locationCreated");
                Log.d(TAG, "Inlocation reciever");
                traceCWrapper.provideLocation(tcLocationEvent);
            }
        };
        LocalBroadcastManager.getInstance(context).registerReceiver(
                locationReceiver, new IntentFilter("locationCreated")
        );


        Log.d(TAG, "inside updating trace");
        //Start CallbackTimer
        startCallbackTimer();

    }

    private void CallbackUpdate() {

    /*    callbackRunnable = new Runnable(){
            @Override
            public void run() {
                Log.d(TAG, "calling callback");
                traceCWrapper.getLatestTraceResult();
                callbackHandler.postDelayed(this, 1000);
            }
        };*/
    }


    private void startCallbackTimer(){
        Log.d(TAG, "I get in here callback");
        callbackRunnable = new Runnable(){
            @Override
            public void run() {
                Log.d(TAG, "calling callback");
                traceCWrapper.getLatestTraceResult();
                callbackHandler.postDelayed(this, 1000);
            }
        };
        callbackHandler.postDelayed(callbackRunnable, 1000);
    }

    private void stopCallbackTimer(){
        callbackHandler.removeCallbacks(callbackRunnable);
    }



    //Calls TraceCWrapper upadate maps and passes the dynamic maps
/*    public void updateMaps(String[] dynamicMaps){
        traceCWrapper.updateMaps(dynamicMaps dynamicmaps){

        }
    }*/

    public void stopUpdatingTrace(){

        boolean stopSensors = true;
        if(stopSensors){
            stopUpdatingSensors();
        }

        //Callback Timer
        stopCallbackTimer();

        //State
        isRunning = false;

        //Trace terminate
        if (_traceCDontActuallyUse == false){
            traceCWrapper.terminate();
        }
    }

    private void stopUpdatingSensors() {

        //todo
        //stop the event bus
        //stop the service


    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public void provideManualLocation(TraceManualLocation manualLocation){

        if(isRunning){
        }else{
            Log.e(TAG, "Calling provideManualLocation, but is running is set to false");
        }
        if(!_traceCDontActuallyUse){
            traceCWrapper.provideManualLocation(manualLocation);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public void provideManualHeadingCorrection(TraceManualHeading traceManualHeading){

        if(isRunning){
        }else{
            Log.e(TAG, "Calling provideHeadingCorrection, but is running is set to false");
        }

        if (!_traceCDontActuallyUse){
            traceCWrapper.provideManualHeading(traceManualHeading);
        }

    }

    public void updateParameter(TraceCVarParameter traceCVarParameter, double value){
        if(isRunning){
        }else{
            Log.e(TAG, "Calling updateparameter, but is running is set to false");
        }
        //todo
        //callback async
    }


    //Private [START]

    boolean isInitialised = false;

    public boolean isInitialised() {
        if(!isInitialised){

        }else{
            //todo
            //send to didfinishinitialisation? confirm isMagConsistentAtInit is true
        }

        return isInitialised;
    }

    private boolean isMagConsistantAtInit = false;
    private Timer callbackTimer;


/*    public traceCallBack(int seconds){
        callBackTimer = new Timer();
        callBackTimer.schedule(new callUpdate(), seconds*1000);
    }*/

    class callUpdate extends TimerTask{

        @Override
        public void run() {
            //traceCWrapper.getLatestTraceResult();


        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_trace_manager);
    }

}

我没有足够的空间来添加TraceCWrapper文件,但是该库的加载方式为:

    static CLibrary lib = Native.loadLibrary("com.waymap.app.traceandroid", CLibrary.class);

并且作为主要示例,该方法在TraceCWrapper中以以下方式接收traceCWrapper.provideDeviceMotion():

    //Provide Device Motion
    public static boolean provideDeviceMotion(TCIMUEvent mTCIMUEvent, int Status, double userHeadingDeg, float rotationMode){

        DeviceMotion dM = new DeviceMotion();
        dM.setTcimuEvent(mTCIMUEvent);
        dM.setStatus(Status);
        dM.setUserHeadingDeg(userHeadingDeg);
        dM.setRotationMode(rotationMode);
        if(isRunning) {

            new sendToTraceHandleImuEvent().execute(dM);
            isInitalized = true;
            return isInitalized;
        }else{
            Log.i(TAG, "IMU update ignored as not running");
            isInitalized = false;
            return isInitalized;
        }
    }
    public static class sendToTraceHandleImuEvent extends AsyncTask<DeviceMotion,Void,Void>{

        @Override
        protected Void doInBackground(DeviceMotion... devicemotions) {
            /*public class Arg extends Structure {
                public devicemotions[] var1 = new byte[9];
                public devicemotions[] var2 = new byte[5];
            }*/
            Log.d(TAG, "InTraceCwrapper Again, provideIMU");

            lib.TraceHandleImuEvent(devicemotions[0].getTcimuEvent(), devicemotions[0].getStatus(), devicemotions[0].getUserHeadingDeg(), devicemotions[0].getRotationMode());
            return null;
        }

    }

您将不得不为大量的日志记录和多余的代码辩解,因为我已经为此苦苦挣扎了一段时间。

通过我的TCIMUEvent时,我正在使用如下结构注释:

@Structure.FieldOrder({ "time", "accel", "accelValid", "mag", "magValid", "gyro", "gyroValid", "pressure", "pressureValid", "temperature", "temperatureValid"})
public class TCIMUEvent extends Structure implements Serializable {

    public double time;
    public float[] accel = new float[3];
    public boolean accelValid;
    public float[] mag = new float[3];
    public boolean magValid;
    public float[] gyro = new float[3];
    public boolean gyroValid;
    public float pressure;
    public boolean pressureValid;
    public float temperature;
    public boolean temperatureValid;

    public TCIMUEvent(double time, float[] accel, boolean accelValid, float[] mag, boolean magValid, float[] gyro, boolean gyroValid, float pressure, boolean pressureValid, float temperature, boolean temperatureValid) {
        this.time = time;
        this.accel = accel;
        this.accelValid = accelValid;
        this.mag = mag;
        this.magValid = magValid;
        this.gyro = gyro;
        this.gyroValid = gyroValid;
        this.pressure = pressure;
        this.pressureValid = pressureValid;
        this.temperature = temperature;
        this.temperatureValid = temperatureValid;
    }
}

所需的Java C映射:

    My Java Library to map:

    void TracehandleLocationEvent(TCLocationEvent tcLocationEvent);

    void TracehandleManualLocationEvent(TCManualLocationEvent tcManualLocationEvent);

    void TracehandleManualHeadingEvent(TCManualHeadingEvent tcManualHeadingEvent);

    void TracehandleManualInitialLocation(TCLocationEvent initialLocationEvent);

    void TraceHandleImuEvent(TCIMUEvent tcimuEvent, int Status, double userHeadingDeg, float rotationMode);

    void TraceGetResult(Double uptime, Pointer traceResult_out);

    -------- These map retrospectively to C:---------

    void TraceHandleLocationEvent (const Trace_locationSample_t *locationSample)

    void TraceHandleManualLocationEvent(const Trace_manualLocationSample_t
  *manualLocationSample)

    void TraceHandleManualHeadingEvent(const Trace_manualHeadingSample_t
  *manualHeadingSample)

     void TraceHandleLocationEvent (const Trace_locationSample_t *locationSample)

     void TraceHandleImuEvent(Trace_imuDataSample_t *imuDataSample, int *status,
  double *userHeadingDeg, StrapdownStreaming_RotationMode *currentRotateMode)

  void TraceGetResult(double time, Trace_Result_t *TraceResult)
java android java-native-interface jna android-native-library
1个回答
0
投票

SIGSEGV JNA映射错误通常是由于访问您不拥有的本机内存引起的。问题各不相同,但首先要看的是结构类型映射和方法/函数参数映射。

作为一个特定示例(可能还有更多),您的代码包括此映射:

void TraceHandleImuEvent(TCIMUEvent tcimuEvent, int Status,
    double userHeadingDeg, float rotationMode);

但是,本机映射在此处不期望intdoublefloat。它需要指针:

void TraceHandleImuEvent(Trace_imuDataSample_t *imuDataSample, int *status,
    double *userHeadingDeg, StrapdownStreaming_RotationMode *currentRotateMode)

((TCIMUEvent之类的结构作为参数传递时会自动映射到其指针,这样就可以了。)

发生的情况是您正在传递int作为状态信息(例如8),但是本机代码在考虑“在存储位置0x8中存储了一个整数”。您不拥有该内存,因此没有该错误。

IntByReference在这里是正确的类型映射,并且对于许多这样的函数自变量。

© www.soinside.com 2019 - 2024. All rights reserved.