나는 K & R의 연습 문제를 연구 중이며 04-06을 다음과 같이 확장하는 동안 이상한 버그가 발생했습니다. 문자열 이름이있는 변수를 허용하십시오. 솔직히, 나는 실제로 버그 (꽤 간단하게 - 아래에 설명 됨)를 고치지 만, 처음에 왜 에러가 발생했는지 알고 싶습니다.snprintf에 비어 있지 않은 문자열을 전달하면 관련이없는 char * 배열로 인해 주소가 변경됩니다.
이 문제에 익숙하지 않은 사용자는 기본적으로 문자 이름을 사용하여 변수를 저장하고 호출 할 수있는 명령 줄 계산기 (폴란드어 표기법 사용)를 작성해야합니다. 문제가 발생하는 위치
다음은 관련 코드입니다 :
#define MAXOPLEN 1000
int varCount = 1;
char **keys;
char **values;
// changing the declaration to:
// char strOps[][STROPCOUNT] = { ... };
// fixed the issue
char *strOps[STROPCOUNT] = { "dupe", "swap", "del", "print",
"clr", "sin", "cos", "tan",
"exp", "pow", "ln", "log",
"mem", "re"};
main() {
keys = malloc(varCount * sizeof(char[MAXOPLEN]));
keys[0] = "ans";
values = malloc(varCount * sizeof(char[MAXOPLEN]));
values[0] = "0.0";
... // Other stuff related to the program
}
// flag is unrelated to the problem I'm asking about. It just checks to see
// if the variable name used to store value n is 'ans', which is where
// the last returned value is stored automatically
void memorize(char s[], double n, bool flag) {
... // small conditional block for flag
for (i = 0; i < varCount; i++) {
if (equals(keys[i], s)) {
found = True;
// Next line is where the program actually breaks
snprintf(values[i], MAXOPLEN, "%f", n);
break;
}
}
if (!found) {
i = varCount;
varCount++;
keys = realloc(keys, varCount * sizeof(char*));
keys[i] = malloc(sizeof(char[MAXOPLEN]));
keys[i] = s;
values = realloc(values, varCount * sizeof(char*));
values[i] = malloc(sizeof(char[MAXOPLEN]));
snprintf(values[i], MAXOPLEN, "%f", n);
}
}
컴파일하고 실행 한 후, 당신이 계산하는 방정식에 입력 한 처음, 모든 것이 원활하게 실행 것으로 보인다. 그러나, 디버깅하는 동안 strOps의 처음 세 char *가 이상하게 다른 주소를 가리 키도록 만들어 졌다는 것을 알게되었습니다. 방정식의 반환 값을 "ans"로 저장하려고하면 문자열 s가 이미 키 이름으로 사용되었는지 확인하려고하는 memorize()의 for-loop를 입력합니다. s의 값 ("ans")과 일치하는 문자열을 가리키는 키 [0]을 올바르게 찾은 다음 double n을 문자열로 변환하고 값 [0]에 저장하려고 시도합니다.
현재 snprintf() 함수 내부 strOps의 처음 세 숯 *는 corecrt_stdio_config.h이 방법 안에 다른 가리키게되지만 :
_Check_return_ _Ret_notnull_
__declspec(noinline) __inline unsigned __int64* __CRTDECL __local_stdio_printf_options(void)
{
// Error occurs after this next line:
static unsigned __int64 _OptionsStorage;
return &_OptionsStorage;
}
상기 코드에 주석 같이
제작 strOps 차원 문자 배열 (char 포인터 배열이 아닌)이 문제를 해결했습니다. 문자 배열은 개별 문자의 값을 변경할 수 없기 때문에 이해할 수 있습니다. 그러나 이해할 수없는 것은 corecrt_stdio_config.h의 해당 메서드가 처음 세 포인터의 값을 변경하는 이유입니다.
감사합니다.
정확한 프로토 타입 함수 선언자를 사용하여 시작하십시오. 'main()'은 더 이상 사용되지 않습니다. 그리고 더 최근의 책을 사용하십시오, K & R은 오래되었습니다. 그것은 현대 C를 가르치지 않는다! 그리고 [ask]를보고 [mcve]를 제공하십시오. 경고없이 컴파일 된 코드라도 이해가되지 않습니다. – Olaf
추가 실행과 관련이있는 경우 함수의 결과를 확인하십시오! 'realloc'이 실패 할 수도 있습니다! – Olaf