私は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の最初の3つのchar *が違ったアドレスを指すように変わっていることが分かりました。方程式の戻り値を "ans"に保存しようとすると、既に文字列sがキー名として使用されていたかどうかを確認しようとするmemorize()のfor-loopに入ります。これはsの値( "ans")と一致する文字列を指し示すキー[0]を正しく見つけ、double nを文字列に変換して値[0]に保存しようとします。
のsnprintf()関数内で、strOpsの最初の3つのchar *が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 2Dを製造します(charポインタの配列ではなく)文字配列が問題を解決しました。文字の配列には個々の文字の値を変更することはできないが、私が理解していないのは、なぜcorecrt_stdio_config.hのそのメソッドが最初の3つのポインタの値を変更したのかということです。
ありがとうございます!
正しいプロトタイプ関数宣言子の使用を開始してください。 'main()'は推奨されません。さらに最近の本を使用すると、K&Rは古くから古くなっています。それは現代Cを教えていない!そして[ask]を見て、[mcve]を提供してください。あなたのコードが警告なしでコンパイルされても、それは意味をなさない。 – Olaf
さらに、実行に関連する関数の結果を確認してください! 'realloc'が失敗するかもしれません! – Olaf