コンパイラのバグ?
Posted: 2013年3月03日(日) 12:26
Windows Vista SP2 32ビット
Dev-C++ 5.4.0
gcc 4.7.0
次のコードが不可解な挙動をして、困りました。
クリップボードに「0;」という文字列をかぎかっこなしでコピーした状態で上のプログラムを実行すると、
「0 1 0 0」というダイアログが表示されます。
これは、start==0,i==1のとき、start<iが偽であることを示しています。
これは意味不明です。
さらに、wsprintf(numberBuffer,"%d %d %d %d",start,i,start<i,num);のあとにstart=1;という行を加えると、
正しく「0 1 1 1」というダイアログが表示されました。
どうしてこのような現象が起きるのでしょうか?
コンパイラを変えたほうがいいのでしょうか?
Dev-C++ 5.4.0
gcc 4.7.0
次のコードが不可解な挙動をして、困りました。
#include <windows.h>
#include <ctype.h>
#include <limits.h>
#include "cpb_main.h"
#include "isprime.h"
static unsigned long long str2ull(const char* buf) {
unsigned long long result=0;
while(*buf!=0 && *buf>='0' && *buf<='9') {
result=result*10+(*buf-'0');
buf++;
}
return result;
}
enum {
STATUS_NONUMBER,
STATUS_NUMBER,
STATUS_INVALIDNUMBER
};
int primeJudge(HWND hWnd,char* prime,const config_t* config) {
HGLOBAL hMem;
WCHAR* str;
int error=0;
int i,length,start,nowlength,status;
if(IsClipboardFormatAvailable(CF_UNICODETEXT)) {
if(OpenClipboard(hWnd)) {
if(hMem=(HGLOBAL)GetClipboardData(CF_UNICODETEXT)) {
WCHAR* strtemp;
if(strtemp=(WCHAR*)GlobalLock(hMem)) {
length=lstrlenW(strtemp);
str=HeapAlloc(GetProcessHeap(),0,(length+1)*sizeof(WCHAR));
if(str)lstrcpyW(str,strtemp); else error=1;
GlobalUnlock(hMem);
} else error=1;
} else error=1;
CloseClipboard();
} else error=1;
} else error=1;
if(error)return 0;
if(config->readMax>0 && config->readMax<2097152) { /* readmax<2^21 */
int kyoyo_length=config->readMax*1024/sizeof(WCHAR);
if(length>kyoyo_length) {
if(config->noReadOverMax) {
HeapFree(GetProcessHeap(),0,str);
return 0;
}
length=kyoyo_length;
}
}
status=STATUS_NONUMBER;
for(i=0;i<length;i++) {
switch(status) {
case STATUS_NONUMBER:
if(isdigit((int)str[i])) {
nowlength=1;
status=STATUS_NUMBER;
start=i;
} else if((int)str[i]=='.' && !config->stopOnPeriod) {
nowlength=0;
status=STATUS_INVALIDNUMBER;
}
break;
case STATUS_NUMBER:
case STATUS_INVALIDNUMBER:
if(isdigit((int)str[i])) {
nowlength++;
if(nowlength>19)status=STATUS_INVALIDNUMBER;
} else if((int)str[i]=='.' && !config->stopOnPeriod) {
status=STATUS_INVALIDNUMBER;
} else if(!config->ignoreComma|| (int)str[i]!=',') {
if(status==STATUS_NUMBER) {
int j,num=0;
char numberBuffer[32];
unsigned long long target;
for(j=start;j<i;j++) {
MessageBox(hWnd,"aaa","test",MB_OK);
if(isdigit((int)str[j]))numberBuffer[num++]=(int)str[j];
}
numberBuffer[num]=0;
wsprintf(numberBuffer,"%d %d %d %d",start,i,start<i,num);
MessageBox(hWnd,numberBuffer,"test",MB_OK);
target=str2ull(numberBuffer);
if(target<=LLONG_MAX && isprime(target)) {
lstrcpy(prime,numberBuffer);
HeapFree(GetProcessHeap(),0,str);
return 1;
}
}
status=STATUS_NONUMBER;
}
break;
}
}
if(status==STATUS_NUMBER && (int)str[i]==0) {
int j,num=0;
char numberBuffer[32];
unsigned long long target;
for(j=start;j<i;j++) {
if(isdigit((int)str[j]))numberBuffer[num++]=(int)str[j];
}
numberBuffer[num]=0;
target=str2ull(numberBuffer);
if(target<=LLONG_MAX && isprime(target)) {
lstrcpy(prime,numberBuffer);
HeapFree(GetProcessHeap(),0,str);
return 1;
}
}
HeapFree(GetProcessHeap(),0,str);
return 0;
}
「0 1 0 0」というダイアログが表示されます。
これは、start==0,i==1のとき、start<iが偽であることを示しています。
これは意味不明です。
さらに、wsprintf(numberBuffer,"%d %d %d %d",start,i,start<i,num);のあとにstart=1;という行を加えると、
正しく「0 1 1 1」というダイアログが表示されました。
どうしてこのような現象が起きるのでしょうか?
コンパイラを変えたほうがいいのでしょうか?