[英]Changing from assignment operator "=" to memcpy for copying bytes resulting in segmentation fault
我編寫了代碼以將較小的 BMP 文件 (A) 放在 Android 本機代碼中的較大 BMP 文件 (B) 中。
編輯:有關 fileA 和 fileB 的更多詳細信息
//initialised as global variables
char * fileA;
char * fileB;
//file A and B are passed in to native C as byte arrays from Java
fileA=(char *) env->GetByteArrayElements(bufferA,&isCopy);
fileB=(char *) env->GetByteArrayElements(bufferB,&isCopy);
fileA 由依次放置的 4 個組的所有 BMP 的 BMP 數據組成。
fileB 是我要寫入的較大文件的 BMP。
我的初始實現使用“=”賦值運算符從文件A逐字節復制到文件B。兩者都初始化為char arrays。
我有 4 組用於文件 A 的 BMP。每組的 BMP 大小相同。 第 1 組為 376 x 54,第 2 組為 297 x 48,第 3 組為 885 x 83,第 4 組為 238 x 108。
將文件 A 中的 1 個 BMP (BMP X) 寫入文件 B 的簡化代碼。
//calculate offset on where to write in fileB
offset = ycoord_of_BMP_X * width_of_file_B + xcoord_of_BMP_X*BYTES_PER_PIXEL;
for (int a = 0; a < height_of_BMP_X; a++){
for (int b = 0; b< width_of_BMP_X; b++){
fileB[offset+ a*width_of_BMP_X + b] = fileA[position_of_BMP_X_in_file_A + (height_of_BMP_X-a-1)*width_of_BMP_X*BYTES_PER_PIXEL + b];
}
offset = offset + width_of_fileB*BYTES_PER_PIXEL-width_of_BMP_X;
}
這工作正常,沒有分段錯誤。 這使我得出結論,該算法及其實現很好。
我用 memcpy 替換了內部 for 循環,並得到以下代碼(再次簡化):
for (int a = 0; a < height_of_BMP_X; a++){
memcpy(fileB[offset+ a*width_of_BMP_X],fileA[position_of_BMP_X_in_file_A + (height_of_BMP_X-a-1)*width_of_BMP_X*BYTES_PER_PIXEL],width_of_BMP_X*BYTES_PER_PIXEL]);
offset = offset + width_of_fileB*BYTES_PER_PIXEL-width_of_BMP_X;
}
必須強調,我在這兩種情況下引用的 fileA 和 fileB 幾乎相同(為清楚起見,摘錄如下)。 我只刪除了“+b”,因為 memcpy 不再需要它。
//the assignment case
fileB[offset+ a*width_of_BMP_X+b]
//memcpy case
fileB[offset+ a*width_of_BMP_X]
第 3 組和第 4 組 BMP 發生分段錯誤(致命信號 11 (SIGSEGV),代碼 1 (SEGV_MAPERR))。 當組 3 達到 a = 52 時報告分段錯誤。即。 memcpy 在 83 個循環中的前 52 個是成功的。 對於第 4 組,它是 108 個循環中的 92 個。
我打印出 fileA 和 fileB arrays 中引用的數組位置,例如外循環中每次迭代的“初始 position x”的值,它與兩種實現都匹配。
分段錯誤是否是 memcpy 進行某種優化的結果,導致發生競爭條件?
謝謝你。
考慮使用結構來對圖像的數據進行分組。 圖像的大小與圖像數據相關。 這里有一個建議:
typedef struct
{
int x,y;
} Coord_s;
typedef struct //Descriptor of an image
{
void * PixelData;
Coord_s Size;
int BytePerLine; // = Size.x * BYTES_PER_PIXEL + possible padding
} Image_s;
void CopyImageRect(Image_s* pDst, Coord_s DstTopLeft, Image_s const* pSrc, Coord_s SrcTopLeft, Coord_s Size)
{
//Copies a rectangle of <Size> from Image <pSrc>'s <SrcTopLeft> to <pDst>'s <DstTopLeft>
//Prepare pointers to pixel data of top-left corner
char* pSrcPix = (char*)pSrc->PixelData + SrcTopLeft.y*pSrc->BytePerLine + SrcTopLeft.x*BYTES_PER_PIXEL;
char* pDstPix = (char*)pDst->PixelData + DstTopLeft.y*pDst->BytePerLine + DstTopLeft.x*BYTES_PER_PIXEL;
for (int y = Size.y; y--;) //for each line
{
memcpy (pDstPix, pSrcPix, Size.x*BYTES_PER_PIXEL);
pSrcPix += pSrc->BytePerLine; //next line
pDstPix += pDst->BytePerLine; //next line
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.