関数呼び出し時に(共有オブジェクト内で定義された)変数のアドレスが失われています。それを証明するために、変数num_accountsの値を意図的に55に設定しました。関数get_num_accounts()が実行を開始すると、この変数へのポインタが正しく受信されませんでした。私の証明は、このgdbのセッションです:関数呼び出し時に変数のアドレスが不正確になる
accounts_init() at accounts.c:31
31 err_code=read_accounts();
(gdb) print num_accounts
$1 = 0
(gdb) print &num_accounts
$2 = (account_idx_t *) 0x7ffff767c640 <num_accounts>
(gdb) set var num_accounts=55
(gdb) print num_accounts
$3 = 55
(gdb) s
read_accounts() at accounts.c:66
66 err_code=get_num_accounts(&num_accounts);
(gdb) s
get_num_accounts (num_accounts_ptr=0x604780 <num_accounts>) at accounts.c:119
119 *num_accounts_ptr=0;
(gdb) print num_accounts
$4 = 55
(gdb) print *num_accounts_ptr
$5 = 0
(gdb)
(gdb) print num_accounts_ptr
$6 = (account_idx_t *) 0x604780 <num_accounts>
(gdb)
変数NUM_ACCOUNTS個のアドレス0x7ffff767c640ですが、私は0x604780機能が実行されたときに、なぜ、このような奇妙なものが起こるのを取得しますか?
機能get_num_accounts()このあるのソースコード:
typedef unsigned short account_idx_t;
グローバル変数NUM_ACCOUNTS個がでaccounts.cファイルで定義されている:
err_code_t get_num_accounts(account_idx_t *num_accounts_ptr) {
err_code_t err_code;
uint32_t file_size;
div_t div_result;
unsigned short number;
*num_accounts_ptr=0;
err_code=get_dir();
if (err_code!=ERR_NO_ERROR) return err_code;
err_code=get_file(ACCOUNTS_FILENAME,sizeof(ACCOUNTS_FILENAME),&file_size);
if (err_code!=ERR_NO_ERROR) return err_code;
div_result=div(file_size,sizeof(tbl_account_t));
if (div_result.rem!=0) {
return ERR_BAD_CONFIG_FILE_FORMAT;
}
number=div_result.quot;
*num_accounts_ptr=number;
return ERR_NO_ERROR;
}
タイプaccount_idx_tは以下のように定義されます初め:
account_idx_t num_accounts=0;
Bas関数が何をしているのかは、ファイルのサイズを取得し、ファイルを読む前にそのファイルに含まれるレコードの数を計算することです。 (そのデータベース)
そして、これはget_num_accounts()関数をcalles、呼び出し元のコード、次のとおりです。私は-fPICフラグとライブラリをコンパイルしています
err_code_t accounts_init(void) {
err_code_t err_code;
err_code=read_accounts();
if (err_code!=ERR_NO_ERROR) return err_code;
return ERR_NO_ERROR;
}
err_code_t read_accounts(void) {
err_code_t err_code;
int ret;
err_code=get_num_accounts(&num_accounts);
if (err_code!=ERR_NO_ERROR) return err_code;
if (num_accounts==0) return ERR_NO_ERROR;
int fd=open(filename_buf,O_RDONLY); // filename_buf is global, it holds filename from previous call
if (fd==-1) {
return ERR_SYS_ERROR;
}
ret=read(fd,accounts,sizeof(tbl_account_t)*num_accounts);
if (ret==-1) {
return ERR_SYS_ERROR;
}
ret=close(fd); // TO_DO: validate return value of close(fd)
if (ret==-1) {
return ERR_SYS_ERROR;
}
return ERR_NO_ERROR;
}
:
[[email protected] src]$ make accounts.o
gcc -g -ffunction-sections -fdata-sections -Wall -Wextra -Wunreachable-code -Wmissing-prototypes -Wmissing-declarations -Wunused -Winline -Wstrict-prototypes -Wimplicit-function-declaration -Wformat -D_GNU_SOURCE -fshort-enums -fPIC -c accounts.c
なしありソースコード内のどこにでも別の 'num_accounts'シンボルがあると、私はそれを二重にチェックしました:
[[email protected] src]$ nm *o|grep num_accounts
0000000000000000 T get_num_accounts
0000000000000000 B num_accounts
[[email protected] src]$
さらなるデバッグ手順についてのご意見はありますか?
GDBがうまくいかないです。だから愚かな質問かもしれない。あなたは 'get_num_accounts'に足を踏み入れたり、踏み込んだりしていますか?あなたが '* num_accounts_ptr'を読んでいるときに踏み込んでいるなら、それは範囲外です。 – MotKohn
@MotKohnは、 's'コマンドでステップして、 'n'コマンドを実行します。 – Nulik
再度質問して申し訳ありませんが、0x7ffff767c640は有効なアドレスのようには見えません。ちょっと高すぎますね。 – MotKohn