簡體   English   中英

從賦值運算符“=”更改為 memcpy 以復制字節導致分段錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM