記事のディレクトリ
序文
今日、同僚が質問をしました。関数パラメーターでポインターを渡すことは非常に一般的なシナリオです。ここで再編成して記録します。今後同様の質問がある場合は、この小さな要約を投稿してください。
コード:バージョン1
void do_malloc(char *p, int size)
{
p = (char *)malloc(size + 1);
memset(p, 0, size + 1);
}
int main(int argc, char *argv[])
{
char *pData = 0;
do_malloc(pData, 128);
sprintf(pData, "%s", "abc");
printf(pData);
return 0;
}
コードの本来の目的は次のとおりです。do_work()関数は、システムヒープスペースのサイズバイトに適用され、メイン関数でpDataポインターを返します。
ただし、Segmentation fault (core dumped)
:エラー。
理由を分析する
char *タイプのポインタは、リモコンと見なすことができます。このポインタに値を割り当てると、リモコンで制御できるデバイスにリモコンをバインドするのと同じことになります。
実施したchar *pData = 0;
次の図に示すように、pDataの内容は空です。これは、リモートコントロールがどのデバイスにもバインドされていないことと同じです。
実施したdo_work(pData, 128);
ここで渡されるパラメーターはpData自体であるため、void do_work(char *p, int size)
関数に入った後、実際のパラメーターpDataの内容が仮パラメーターpに割り当てられ、ポインターpの内容も空になります。つまり、リモコンpはバインドされません。以下に示すように:
実施したp = (char *)malloc(size + 1);
この文の機能は、適用されたヒープスペースの最初のアドレスをpに割り当てることです。つまり、次の図に示すように、pはメモリ内のスペースを指します。これは、pのリモートコントローラーをデバイスにバインドするのと同じであり、このデバイスを制御できます。
この時点で、プログラムがクラッシュする理由がわかりました。ポインタpが割り当てられていても、実際のパラメータpDataの内容は常に空であるため、do_malloc関数から戻った後も、pDataはnullポインタのままであるため、クラッシュしました。 。もちろん、pが指すヒープスペースもリークされます。
コード:バージョン2
コードの本来の目的は、do_malloc関数のヒープスペースを適用してから、このスペースの最初のアドレスをpDataに割り当てることです。do_malloc関数で、システム関数mallocを呼び出すと、割り当てられたスペースの最初のアドレスが正常に返されます。重要なのは、この最初のアドレスをpDataポインターに送信することです。つまり、pDataポインター変数の値はの最初のアドレスと同じです。ヒープスペース。
したがって、真ん中の関数を介してこの関数を実行する方法は、次のコードです。
void do_malloc(char **p, int size)
{
*p = (char *)malloc(size + 1);
memset(*p, 0, size + 1);
}
int main(int argc, char *argv[])
{
char *pData = 0;
do_malloc(&pData, 128);
sprintf(pData, "%s", "abc");
printf(pData);
return 0;
}
実施したchar *pData = 0;
この文に変更はありません。
実施したdo_malloc(&pData, 128);
pData自体がポインターであり、アドレス文字&がポインターのポインター(第2レベルのポインター)であるため、pDataポインターのアドレスは、実際のパラメーターとして渡されます。したがって、do_malloc関数の最初のパラメーターは次のようになります。この時点での図に示すように、char **タイプとして定義されています。
この時点で、pはセカンダリポインタです。パラメータが割り当てられると、pの内容はポインタ変数pDataのアドレスになります。つまり、pは変数pDataを指します。
実施した*p = (char *)malloc(size + 1);
まず*p
、この文の意味を理解してください。前に述べたように、pは変数pDataを指すポインターです。次に、pの前に値演算子*を追加することは、ポインターpの値を取り出すことと同じであり、その中の値はpDataです。
したがって、次の図に示すように、malloc関数によって返されるヒープスペースの最初のアドレスは、pDataに割り当てられるのと同じです。
この時点で、リモートコントロールのpDataは割り当てられたヒープスペースにバインドされているため、pDataの操作に問題はありません。
> OF:コロンビアロード(公開番号: IOTタウンのIOT )
>ほぼ知っている:コロンビアロード
> B駅:コロンビアロードシェア
>ナゲッツ:コロンビアロードシェア
> CSDN:コロンビアロードシェア
記事が良いと思う場合は、転送して友達と共有してください。組み込み開発における10年以上のプロジェクトの実際の戦闘経験
を要約して共有します。あなたが失望することはないと信じています!
転載:転載へようこそが、著者の同意なしに、この声明を保持し、元のリンクを記事に記載する必要があります。
推奨読書
[1] gdbの基本的なデバッグ原理は非常に単純です
[2]プロデューサーモードとコンシューマーモードのダブルバッファリングテクノロジー
[3]詳細なLUAスクリプト言語。デバッグの原理を完全に理解できます
[4]段階的な分析-Cオブジェクト指向プログラミングでそれを実装する方法
[5]暗号化と証明書に関するもの