【问题标题】:Fatal signal 16 (SIGSTKFLT) has been occured unexpectedly致命信号 16 (SIGSTKFLT) 意外发生
【发布时间】:2014-01-14 00:36:20
【问题描述】:

今天我遇到了一个奇怪的问题。 我在三台设备上安装了我的应用程序

  1. 华硕Transformer Pad Infinity TF700T
  2. 三星 I9082 Galaxy Grand Duos
  3. LG Optimus L7 II Dual p715

首先,我使用所有这些设备在调试模式下从 Eclipse 运行我的应用程序。而且没关系。

然后,我以通常的方式运行我的应用程序(直接在设备上)。就这样,我所有的坏事都开始了。对于 1 和 2 设备都可以。但是 3 设备没有像我预期的那样工作。 LogCat 向我显示了以下致命错误:

01-14 01:36:47.529: E/dalvikvm(11294): threadid=1: 卡住 threadid=14,放弃 01-14 01:36:47.529: A/libc(11294): 致命信号 16 (SIGSTKFLT) 在 0x00002c1e (code=-6),线程 11315 (AsyncTask #4)

我真的不明白,发生了什么以及为什么 1 和 2 设备都可以正常工作,但第三个却不能。

谁能解释一下,这个错误是什么意思以及如何纠正?

UPD1我不使用 NDK 调用和任何第三方库。

UPD2导致错误的大代码sn-p是(我在这里包括所有事件调用绘制过程并停止它):

//I included all imports for sure that I don't use nothing instead of standard things
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.WindowManager;

public class MyLiveWallpaper extends WallpaperService {
    public static final String CONFIGS = "configs";
    private WallpaperEngine we;

    @Override
    public void onCreate() {
            super.onCreate();
    }

    @Override
    public void onDestroy() {
            super.onDestroy();
            if(we.myDrawTask!=null){
                    we.myDrawTask.cancel(false);
            }
    }

    @Override
    public Engine onCreateEngine() {
            we = new WallpaperEngine();
            return we;
    }

    //DeviceScreenSize is some class where I just incapsulate screen width, height and depth obtained in getScreenSize() method
    DeviceScreenSize dss = new DeviceScreenSize(0, 0, 0);

    class WallpaperEngine extends Engine implements
                    OnSharedPreferenceChangeListener {
            //Some definitions below
            ............................
            public DrawTask myDrawTask = null;
            ............................
            //Some definitions above

            WallpaperEngine() {
                    ..............
                    doubleTapDetector = new GestureDetector(HDLiveWallpaper.this,
                                    new SimpleOnGestureListener() {
                            @Override
                            public boolean onDoubleTap(MotionEvent e) {
                                    if (mTouchEvents) {
                                            mLastDrawTime = 0;
                                            if(myDrawTask!=null){
                                                    myDrawTask.stopAnimationFlag = true;
                                            }
                                            else{
                                                    myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                                                    myDrawTask.execute();
                                            }
                                            return true;
                                    }
                                    return false;
                            }
                    });
            }

            @Override
            public void onCreate(SurfaceHolder surfaceHolder) {
                    super.onCreate(surfaceHolder);
                    // Register receiver for media events
                    IntentFilter filter = new IntentFilter();
                    filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
                    filter.addAction(Intent.ACTION_MEDIA_CHECKING);
                    filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
                    filter.addAction(Intent.ACTION_MEDIA_EJECT);
                    filter.addAction(Intent.ACTION_MEDIA_NOFS);
                    filter.addAction(Intent.ACTION_MEDIA_REMOVED);
                    filter.addAction(Intent.ACTION_MEDIA_SHARED);
                    filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
                    filter.addDataScheme("file");
                    mReceiver = new BroadcastReceiver() {
                            @Override
                            public void onReceive(Context context, Intent intent) {
                                    String action = intent.getAction();
                                    if (action.equals(Intent.ACTION_MEDIA_MOUNTED) || action.equals(Intent.ACTION_MEDIA_CHECKING)) {
                                            mStorageReady = true;
                                            setTouchEventsEnabled(true);

                                            if(myDrawTask!=null){
                                                    myDrawTask.cancel(false);
                                            }
                                            myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                                            myDrawTask.execute();

                                    } else {
                                            mStorageReady = false;
                                            setTouchEventsEnabled(false);
                                            if(myDrawTask!=null) myDrawTask.cancel(false);
                                    }
                            }
                    };
                    registerReceiver(mReceiver, filter);

                    // Register receiver for screen on events
                    mScreenOnReciever = new BroadcastReceiver() {
                            @Override
                            public void onReceive(Context context, Intent intent) {
                                    System.out.println(Intent.ACTION_SCREEN_ON);
                                    if (mScreenWake) {
                                            mLastDrawTime = 0;
                                    }
                                    if(myDrawTask!=null){
                                            myDrawTask.cancel(false);
                                    }
                                    myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                                    myDrawTask.execute();
                            }
                    }; 
                    registerReceiver(mScreenOnReciever, new IntentFilter(Intent.ACTION_SCREEN_ON));

                    mScreenOffReciever = new BroadcastReceiver() {
                            @Override
                            public void onReceive(Context context, Intent intent) {
                                    System.out.println(Intent.ACTION_SCREEN_OFF);
                                    if (mScreenWake) {
                                            mLastDrawTime = 0;
                                    }
                                    if(myDrawTask!=null){
                                            myDrawTask.cancel(false);
                                    }
                            }
                    }; 
                    registerReceiver(mScreenOffReciever, new IntentFilter(Intent.ACTION_SCREEN_OFF));

                    setTouchEventsEnabled(mStorageReady);
            }

            @Override
            public void onDestroy() {
                    super.onDestroy();
                    mPrefs.unregisterOnSharedPreferenceChangeListener(this);
                    unregisterReceiver(mReceiver);
                    unregisterReceiver(mScreenOnReciever);
                    unregisterReceiver(mScreenOffReciever);
                    if(myDrawTask!=null){
                            myDrawTask.cancel(false);
                    }
            }

            @Override
            public void onVisibilityChanged(boolean visible) {
                    mVisible = visible;
                    if (visible) {
                            if(myDrawTask!=null){
                                    myDrawTask.cancel(false);
                            }
                            myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                            myDrawTask.execute();
                            mLastDrawTime = 0;
                    } else {
                            if(myDrawTask!=null){
                                    myDrawTask.cancel(false);
                            }
                    }
            }

            @Override
            public void onSurfaceChanged(SurfaceHolder holder, int format,
            int width, int height) {
                    super.onSurfaceChanged(holder, format, width, height);
                    .....................
                    if (mBitmap != null) {
                            mBitmap.recycle();
                    }

                    if(myDrawTask!=null){
                            myDrawTask.cancel(false);
                    }
                    myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                    myDrawTask.execute();
            }

            @Override
            public void onSurfaceCreated(SurfaceHolder holder) {
                    super.onSurfaceCreated(holder);
                    if(myDrawTask!=null){
                            myDrawTask.cancel(false);
                    }
                    myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                    myDrawTask.execute();
                    mLastDrawTime = 0;
            }

            @Override
            public void onSurfaceDestroyed(SurfaceHolder holder) {
                    super.onSurfaceDestroyed(holder);
                    mVisible = false;
                    if(myDrawTask!=null){
                            myDrawTask.cancel(false);
                    }
            }

            @Override
            public void onOffsetsChanged(float xOffset, float yOffset, float xStep,
            float yStep, int xPixels, int yPixels) {
                    mXOffset = xOffset;
                    mYOffset = yOffset;
                    if(myDrawTask!=null){
                            myDrawTask.cancel(false);
                    }
                    myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                    myDrawTask.execute();
            }

            @Override
            public void onTouchEvent(MotionEvent event) {
                    super.onTouchEvent(event);
                    this.doubleTapDetector.onTouchEvent(event);
            }

            public final Bitmap drawableToBitmap(Drawable drawable) {
                    int targetWidth = (mScroll) ? mMinWidth : dss.getWidth();
                    int targetHeight = (mScroll) ? mMinHeight : dss.getHeight();

                    Bitmap bitmap = Bitmap.createBitmap(targetWidth, targetHeight, Config.ARGB_8888);

                    Canvas canvas = new Canvas(bitmap);
                    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                    drawable.draw(canvas);

                    // Rotate
                    .....................

                    // Scale bitmap
                    .....................
                    return bitmap;
            }

            void getScreenSize() {
                    WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
                    Display d = wm.getDefaultDisplay();
                    DisplayMetrics metrics = new DisplayMetrics();
                    d.getMetrics(metrics);

                    // since SDK_INT = 1;
                    dss.setDeviceScreenParams(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);

                    // includes window decorations (statusbar bar/menu bar)
                    if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
                            try {
                                    dss.setDeviceScreenParams((Integer) Display.class.getMethod("getRawWidth").invoke(d), (Integer) Display.class.getMethod("getRawHeight").invoke(d), metrics.densityDpi);
                            } catch (Exception ignored) {}

                    // includes window decorations (statusbar bar/menu bar)
                    if (Build.VERSION.SDK_INT >= 17)
                            try {
                                    DisplayMetrics realSize = new DisplayMetrics();
                                    Display.class.getMethod("getRealMetrics", DisplayMetrics.class).invoke(d, realSize);
                                    dss.setDeviceScreenParams(realSize.widthPixels, realSize.heightPixels, realSize.densityDpi);
                            } catch (Exception ignored) {}
            }

            //
            // ************************
            // DRAW AND ANIMATION TASK
            // ************************
            //
            public class DrawTask extends AsyncTask<Void, Void, Void> {
                    private final SurfaceHolder _surfaceHolder;
                    private Paint myPaint;
                    boolean CancelFlag = false, stopAnimationFlag = false;

                    //HANDLERS
                    private final Handler mDrawHandler = new Handler(){
                            public void handleMessage(android.os.Message msg) { };
                    };

                    //WORKERS
                    private final Runnable mDrawWorker = new Runnable() {
                            public void run() {
                                    if (mDuration > 0)
                                    {
                                            drawFrame();
                                    }
                            }
                    };

                    DrawTask(SurfaceHolder holder, Paint paint){
                            _surfaceHolder = holder;
                            myPaint = paint;
                            CancelFlag = false;
                    }

                    SurfaceHolder getSurfHolder(){
                            return _surfaceHolder;
                    }

                    Paint getPaint(){
                            return myPaint;
                    }

                    @Override
                    protected void onPreExecute() {
                            super.onPreExecute();
                    }   

                    @Override
                    protected Void doInBackground(Void... params) {
                            drawFrame();
                            while(!CancelFlag){}
                            return null;
                    }

                    @Override
                    protected void onPostExecute(Void result) {
                            // TODO Auto-generated method stub
                            super.onPostExecute(result);
                    }

                    @Override
                    protected void onCancelled() {
                            // TODO Auto-generated method stub
                            super.onCancelled();
                            CancelFlag = true;
                    }

                    void drawFrame() {
                            final SurfaceHolder holder = _surfaceHolder;
                            Canvas c = null;
                            boolean getImage = false;

                            try {
                                    // Lock the canvas for writing
                                    c = holder.lockCanvas();

                                    // Do we need to get a new image?
                                    if (mBitmap == null) {
                                            getImage = true;
                                    } else if (mDuration > 0 && mLastDrawTime < System.currentTimeMillis() - mDuration) {
                                            getImage = true;
                                    } else if (mLastDrawTime == 0) {
                                            getImage = true;
                                    }

                                    // Get image to draw
                                    if (getImage) {
                                            // Get a list of files
                                            String[] assets_files = null;
                                            try {
                                                    assets_files = getApplicationContext().getAssets().list("");
                                            } catch (IOException e) {
                                                    e.printStackTrace();
                                            }

                                            List<String> str_list = new ArrayList<String>();
                                            for (int fi = 0; fi < assets_files.length; fi++) {
                                                    String ext = BitmapUtil.getExtension(assets_files[fi]);
                                                    if (ext != null) {
                                                            if (ext.equals("jpg") || ext.equals("jpeg") || ext.equals("png") || ext.equals("gif")) {
                                                                    str_list.add(assets_files[fi]);
                                                            }
                                                    }
                                            }
                                            assets_files = str_list.toArray(new String[str_list.size()]);

                                            // Increment counter
                                            int nFiles = assets_files.length;
                                            if (mRandom) {
                                                    int i = mIndex;
                                                    do {
                                                            mIndex = (int) (Math.random() * nFiles);
                                                    } while (nFiles > 1 && mIndex == i);
                                            } else {
                                                    if (++mIndex >= nFiles) {
                                                            mIndex = 0;
                                                    }
                                            }

                                            InputStream ims = null;
                                            try {
                                                    ims = getAssets().open(assets_files[mIndex]);
                                            } catch (IOException e) {
                                                    e.printStackTrace();
                                            }
                                            d = Drawable.createFromStream(ims, null);

                                            // Read file to bitmap
                                            mBitmap=null;
                                            mBitmap = drawableToBitmap(d);

                                            // Save the current time
                                            mLastDrawTime = System.currentTimeMillis();
                                    } else if (mBitmap != null && mBitmap.isRecycled()){
                                            mBitmap=null;
                                            mBitmap = drawableToBitmap(d);
                                    }
                            } catch (NullPointerException npe) {
                                    holder.unlockCanvasAndPost(c);
                                    return;
                            } catch (RuntimeException re) {
                                    holder.unlockCanvasAndPost(c);
                                    return;
                            }

                            try {
                                    if (c != null) {
                                            int xPos;
                                            int yPos;
                                            if (mScroll) {
                                                    xPos = 0 - (int) (mWidth * mXOffset);
                                                    yPos = 0 - (int) (mHeight * mYOffset);
                                            } else {
                                                    xPos = 0;
                                                    yPos = 0;
                                            }
                                            try {
                                                    c.drawColor(Color.BLACK);
                                                    c.drawBitmap(mBitmap, xPos, yPos, myPaint);        
                                            } catch (Throwable t) {}
                                    }
                            } finally {
                                    if (c != null){
                                            if((mPreviousBitmap==null) || (mPreviousBitmap==mBitmap))
                                                    holder.unlockCanvasAndPost(c);
                                            else{                       
                                                    if(mTransition!=0)
                                                            startAnimation(mTransition, holder, c);
                                                    else
                                                            holder.unlockCanvasAndPost(c);
                                            }
                                                    mPreviousBitmap=null;
                                                    mPreviousBitmap = mBitmap;
                                    }
                            }

                            // Reschedule the next redraw
                            mDrawHandler.removeCallbacks(mDrawWorker);

                            if (mVisible) {
                                    mDrawHandler.postDelayed(mDrawWorker, 1000 / 2);
                            }
                            else{CancelFlag=true;}
                    }



                    void startAnimation(int animNumber, SurfaceHolder holder, Canvas canvas)
                    {
                            switch(animNumber){
                                    case 1:{
                                            canvas.drawBitmap(mBitmap, 0, 0, myPaint);
                                            int tmpPaintAlpha = myPaint.getAlpha();
                                            myPaint.setAlpha(255);
                                            canvas.drawBitmap(mPreviousBitmap, 0, 0, myPaint);
                                            holder.unlockCanvasAndPost(canvas);
                                            myPaint.setAlpha(tmpPaintAlpha);

                                            int i=224;
                                            while(i>=0){
                                                    canvas = holder.lockCanvas();
                                                    canvas.drawBitmap(mBitmap, 0, 0, myPaint);
                                                    myPaint.setAlpha(i);
                                                    canvas.drawBitmap(mPreviousBitmap, 0, 0, myPaint);
                                                    holder.unlockCanvasAndPost(canvas);
                                                    myPaint.setAlpha(255);
                                                    i-=18;
                                            }
                                            mLastDrawTime=System.currentTimeMillis();
                                            break;
                                    }
                                    case 2:{
                                            ....................
                                            break;
                                    }
                            }
                    }
            }
    ...................
    }
    ...................
}

这里每次我们陷入 DrawTask.drawFrame() 方法时都会发生错误,即使没有任何信息 (mTransition==0)。结果我看到了:

(1) 初始图像的第一步和下一个图像正确完成;

(2) 当需要更改第二到第三个等图像时,我只是在非恒定时间段内看到黑屏,然后我再次看到我的初始图像并无限重复 (2) 中的所有内容。任何设置更改都不会改变此行为。

UPD3希望我对此问题的详细描述(UPD1、UPD2)可以帮助找到这种奇怪行为的原因。但是,不幸的是,现在不适合我。

非常感谢!

【问题讨论】:

  • 您在使用 NDK 吗?或者,您是否使用任何包含 NDK 编译代码的第三方库?
  • 您的应用程序崩溃时在做什么?可以看到“libc”,这是底层C++系统代码的崩溃。
  • 我不使用 NDK 或任何其他第三方库。只是一个标准的东西是我逻辑的一部分。该代码是一种简单的动态壁纸,用于在更改事件(按时间、双击或任何其他动作)上以不同的动画幻灯片显示不同的图像。我传递给 AsyncTask 的绘图和动画部分。您可以在上面的 UPD2 部分中看到导致错误的代码。我包括 big sn-p 以便更好地澄清(但直接问题最终出现 - 在 DrawTask.drawFrame() 方法中)。

标签: android android-asynctask signals fatal-error


【解决方案1】:

SIGSTKFLT 在设备内存不足时发生,尤其是。在底层 linux OS 层中使用 malloc() 调用时。当操作系统无法在 malloc 中返回失败时,它会生成此类致命信号。

尝试使用一些节省内存的技术(如后期绑定图像解码)来解决内存不足的设备上的上述问题,因为它们会占用大量内存。

首先,您可以尝试将图像调整为屏幕分辨率或更低,然后再将其发布到画布上。

【讨论】:

  • 但在我看来,我在方法 drawableToBitmap() 中调整图像的大小,并在方法 getScreenSize() 中接收到屏幕宽度和高度。为此,我在转换为位图之前使用方法 drawable.setBounds()。这是正确的吗?或者我应该以另一种方式做到这一点?顺便说一句,即使使用 48x48 图像,我也尝试了我的应用程序并得到了相同的行为。
  • 在上面的代码中,在一些速度较慢的设备上,您可以长时间握住画布。看,这个调用: c = holder.lockCanvas();并且您正在处理要显示的数据,然后解锁画布尝试在异步任务或其他内容中进行所有处理,然后调用drawFrame(),更新画布然后解锁它。例如:updateScreen(){ processFrame(); // 在此处添加所有帧处理 drawFrame(); } drawFrame(){ // 获取并锁定画布 // 在画布上绘制 -> 仅绘制,此处不处理 // 解锁并发布 }
【解决方案2】:

感谢大家对我的支持!我找到了问题的真正原因。这只是解决正确线程问题的一种愚蠢方法。例如,在开始时调用的事件顺序如下:

WallpaperService.onCreate()

onSharedPreferenceChanged()

WallpaperService.onCreateEngine()

Engine.onCreate()

Engine.onSurfaceCreated()(这里创建了 DrawTask #1)

Engine.onSurfaceChanged()(这里创建了 DrawTask #2)

Engine.onVisibilityChanged()(这里创建了 DrawTask #3)

Engine.onOffsetChanged()(这里创建了 DrawTask #4)

Engine.onOffsetChanged()(这里创建了 DrawTask #5)

Engine.onOffsetChanged()(这里创建了 DrawTask #6)

Engine.onOffsetChanged()(这里创建了 DrawTask #7)

Engine.onOffsetChanged()(这里创建了 DrawTask #8)

Engine.onOffsetChanged()(这里创建了 DrawTask #9)

Engine.onOffsetChanged()(这里创建了 DrawTask #10)

Engine.onOffsetChanged()(这里创建了 DrawTask #11)

Engine.onOffsetChanged()(这里创建了 DrawTask #12)

Engine.onOffsetChanged()(这里创建了 DrawTask #13)

DrawTask #2 已停止

DrawTask #3 已停止

DrawTask #4 已停止

DrawTask #6 已停止

DrawTask #5 已停止 ...

因此,如果变量 mVisible 为 true,则我删除了所有 AsyncTask 生成,除了 onVisibilityChanged() 和 onSurfaceChanged()。现在至少我的所有设备都可以了。

【讨论】:

    猜你喜欢
    • 2015-08-04
    • 2015-06-25
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 2012-05-12
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多