致命信号 16 (SIGSTKFLT) 意外发生
Posted
技术标签:
【中文标题】致命信号 16 (SIGSTKFLT) 意外发生【英文标题】:Fatal signal 16 (SIGSTKFLT) has been occured unexpectedly 【发布时间】:2014-01-14 00:36:20 【问题描述】:今天我遇到了一个奇怪的问题。 我在三台设备上安装了我的应用程序
-
华硕Transformer Pad Infinity TF700T
三星 I9082 Galaxy Grand Duos
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);
elseCancelFlag=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() 方法中)。 【参考方案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()。现在至少我的所有设备都可以了。
【讨论】:
以上是关于致命信号 16 (SIGSTKFLT) 意外发生的主要内容,如果未能解决你的问题,请参考以下文章
@IBInspectable 致命错误:在展开可选值时意外发现 nil