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를 실행하지 않으 코드는 복잡성을 많이 증가 시키며 문제에 대해 밝히지 않습니다. 그것은 간단합니다 (하하!) 배열과 포인터 오프셋이 현명하게 작동하지 않는 것입니다.
메모리의 배열 레이아웃은 C 언어로 완전히 지정됩니다. 구현 방식이 달라질 여지는 없습니다. –
아니요, 전 행 우선 순위에 넣은 사람입니다. 그리고 제가 말했듯이, 예제는 주어진대로 작동합니다 - 계산 결과는 출력이 완벽합니다; 오프셋 계산이 잘못된 경우에는 그렇지 않습니다. 동의하셨습니까? – fyngyrz
@fyngyrz 동의하지 않았습니다. 복사의 단순한 경우 (또는 단일 픽셀 (배열 요소)에서만 작동하는 경우) 모든 오프셋을 생성하는 한 반복하는 순서는 중요하지 않습니다. 그러나, 그것에 대해 더 많은 생각을 할 때, 나는 행 - 대 열 순서가 문제라면, 두 번째 수정 ('foo [offset - 1]')이 효과가 있어야한다고 생각한다. – rlibby