2011-02-02 2 views
3

32 비트 모드에서 64 비트 시스템에서 실행되는 OSX 용 C로 작성했습니다. 나는 386을 위해 GCC를 사용하여 컴파일하고있다. 프로젝트는 크다. 나는 컴파일러에서 이상한 행동을 보지 못했다. (아마도 지금까지는.) 애플리케이션은 다중 쓰레드이며,이 코드는 존재하지만, 현재는 단일 쓰레드로 실행 중이다. 위치 독립적 인 clib를 사용하여 컴파일하고 스레드를 사용할 때 posix 스레드를 사용합니다. 이 코드는 btw가 정확히 일 때을 실행하면 똑같이 작동합니다.서명되지 않은 짧은 포인터가 예기치 않은 결과를 반환하고 있습니다. 왜?

다음은 가장 간단한 형식의 문제를 보여주는 간단한 절차입니다. 기본적으로 16 비트 이미지 채널을 3 개의 RGB 채널 (mr, mg, mb) 세트에서 정확히 동일한 크기의 3 개의 RGB 채널 세트 (lr, lg, lb)로 이동합니다. 나는 그것을 덤프하려고 해요으로 조각은 완벽하게 작동합니다 : 당신이 볼 수 있듯이

void lrip_me( unsigned short *mr, // RIP from source image 
       unsigned short *mg, 
       unsigned short *mb, 
       unsigned short *lr, // into RGB layer 
       unsigned short *lg, 
       unsigned short *lb, 
       struct layer *lay, 
       long start,long finish) 
{ 
long xw,yw; 
long xf,yf; 
long x,y; 
unsigned long offset; 

    xw = lay->parent->x; 
    yw = lay->parent->y; 
    xf = xw - 1; 
    yf = yw - 1; 

    for (y=start; y<finish; y++) 
    { 
     for (x=0; x<xw; x++) 
     { 
      offset = (y * xw) + x; 
      if (x==0 || x==xf || y==0 || y==yf) // then on edge 
      { 
       lr[offset] = mr[offset]; 
       lg[offset] = mg[offset]; 
       lb[offset] = mb[offset]; 
      } 
      else 
      { 
       lr[offset] = mr[offset]; 
       lg[offset] = mg[offset]; 
       lb[offset] = mb[offset]; 
      } 
     } 
    } 
} 

는, 이미지 및 가장자리 안쪽 가장자리에 작업이 동일합니다; 나는 단순히 데이터를 움직이고있다. 그리고 이것은 작동합니다 - 이것의 출력은 lr, lg, lb 채널의 이미지입니다.

그러나. 의 다른 절 안에, 내가 읽을 수있는 라인을 변경하는 경우 ...

  lr[offset] = mr[offset-xw]; 
      lg[offset] = mg[offset-xw]; 
      lb[offset] = mb[offset-xw]; 

... 당신이 데이터 페치가에서 오는 것 같이, 한 스캔 라인을 이동하는 이미지의 내부를 기대할 수 전체 스캔 라인의 거리가 멀어 지지만 이동하지 않은 타겟 위치로갑니다. 대신 출력이 완전히 무작위로 보입니다. 반바지가 틀린 경계에, 어쩌면 또는 다른 곳에서 적재 된 것처럼. 이것은 같은 일을합니다 ...

  lr[offset] = mr[offset-1]; 
      lg[offset] = mg[offset-1]; 
      lb[offset] = mb[offset-1]; 

... 거기에 이미지가 수평으로 1 픽셀 이동하는 것을 기대합니다. 동일한 결과 - 가장 순수한 해시입니다.

배열 대신 포인터 수학으로 변경하려고 시도했습니다. // * (mr + offset-1) // 그리고 똑같은 결과를 얻습니다. 라이브러리 및 objc 환경에서 컴파일했습니다. 나는 오프셋을 사용해 보았는데 아마도 컴파일러가 데이터의 크기에 대해 혼란 스러울 것이라고 생각할 것이다. 나는 매번 같은 결과를 얻는다. 오프셋 값은 그대로 사용할 수 있지만 그대로 사용하십시오. 대괄호 안에 수정할 수 없으며, 대괄호 바깥쪽에 수정할 수 없습니다. 단지 대문자로 취급됩니다.

나는 여기서 무슨 일이 일어나는지 알지 못합니다. 누군가가 나를 이해하는 데 도움이된다면 분명히 감사 할 것입니다.

약간의 배경; 이것은 RIP (분리 된 픽셀 제거) 연산입니다. 또는 루프가 현재보고있는 주변의 8 픽셀을 얻을 수 있다면 적어도 될 것입니다. 그래서 가장자리가 다르게 취급됩니다. 이 테스트의 경우

ooo 
oxo 
ooo 

, 내가 삭제 한 모든 RIP를 : 난 항상 보는 모든 8을 볼 수있는 곳 난 단지 그 내부 가장자리에 8 픽셀 lookaround를 실행하지 않으 코드는 복잡성을 많이 증가 시키며 문제에 대해 밝히지 않습니다. 그것은 간단합니다 (하하!) 배열과 포인터 오프셋이 현명하게 작동하지 않는 것입니다.

답변

1

인덱스 함수는 2D 배열이 row-major order 인 것으로 가정합니다.

offset = (y * xw) + x; 

아마 열 우선 순위입니다.

+0

메모리의 배열 레이아웃은 C 언어로 완전히 지정됩니다. 구현 방식이 달라질 여지는 없습니다. –

+0

아니요, 전 행 우선 순위에 넣은 사람입니다. 그리고 제가 말했듯이, 예제는 주어진대로 작동합니다 - 계산 결과는 출력이 완벽합니다; 오프셋 계산이 잘못된 경우에는 그렇지 않습니다. 동의하셨습니까? – fyngyrz

+0

@fyngyrz 동의하지 않았습니다. 복사의 단순한 경우 (또는 단일 픽셀 (배열 요소)에서만 작동하는 경우) 모든 오프셋을 생성하는 한 반복하는 순서는 중요하지 않습니다. 그러나, 그것에 대해 더 많은 생각을 할 때, 나는 행 - 대 열 순서가 문제라면, 두 번째 수정 ('foo [offset - 1]')이 효과가 있어야한다고 생각한다. – rlibby