2017-03-07 13 views
0

参照でpid_tをvoidポインタとして渡して、それをpid_tに型キャストすることに問題があります。voidポインタが正しくpid_tに型キャストする

typedef void * ProcessHandle_t; 

void createProcess(ProcessHandle_t * processHandle) 
{ 
    pid_t newTask = fork(); 

    if(newTask != 0) 
    { 
     /* Parent process */ 
     /* Return a process handle for the main task to use */ 
     *processHandle = &newTask; 
     printf("pid_t output 1: %d\n", *((pid_t *)*processHandle)); 
    } else 
    { 
     while(1){ 
      printf("Child running\n"); 
     } 
    } 

} 

void deleteProcess(ProcessHandle_t processHandle) 
{ 
    pid_t deleteTask = *((pid_t *)processHandle); 

    printf("pid_t output 3: %d\n", deleteTask)); 

    kill(deleteTask, SIGKILL); 
} 

int main() 
{ 
    ProcessHandle_t processHandle; 

    createProcess(&processHandle); 

    printf("pid_t output 2: %d\n", ((pid_t *)*processHandle)); 

    deleteProcess(processHandle); 

    printf("Parent exiting\n"); 

} 

そして、私の出力は次のとおりです:次のように私のコードがある

pid_t output 1: 19876 
pid_t output 2: 19876 
pid_t output 3: 493972479 
Parent exiting 

しかし、私は、なぜ分かりません。同じ種類の逆参照をintで行うと、うまくいきますが、pid_tに対して同じことをすると、私は本当に奇妙な値を得ます。

これはpid_tでは機能しませんが、他の変数タイプでは機能する特定の理由はありますか?

+2

あなたの質問には本当に答えはありませんが、これらの頭痛は正確にtypedefの背後にあるポインタセマンティクスを隠すべきではありません。あなたの "抽象化"があなたのコードを破壊し始めるならば、それは悪い抽象です。 – StoryTeller

+0

'((pid_t *)processHandle)'は 'deleteProcess'の'(pid_t)processHandle'にしてはいけませんか? – DyZ

+3

typedefを追加する手間があるなら、なぜtypedef ptr_t * ProcessHandle_t;間違いなく、より明確で維持可能なものです。あるいは、より良いことに、typedefを忘れて間接を忘れて...元の 'ptr_t'をそのまま使用してください! – paulsm4

答えて

0

ローカル変数は、定義された関数が戻ったときに範囲外になることに注意してください。あなたがここに

*processHandle = &newTask; 

を持ってcreateProcess機能で

あなたはローカル変数newTask*processHandleポイントを作ります。

が返ってきたとき、以前にnewTask変数が占有していたメモリは、もはや存在しなくなりました(実際は次の関数呼び出しで再利用されます)。

このポインタを参照解除すると、の未定義の動作が発生します

ポインタを使用してnewTaskの内容をコピーする場合は、コピーされた値にメモリを割り当てる必要があります。実際には、を新しく割り当てられたメモリにコピーします。そして、あなたがメモリを割り当てているなら、あなたはもちろんそれを解放しなければなりません。

より簡単な解決策は、ポインタをまったく使用しないことです。ポインタを避けることは、通常、未定義の動作やクラッシュを避けるための非常に良い方法です。

関連する問題