2015-10-04 84 views
0

我在寫這個程序來練習C語言編程,這是我的代碼:C編程:鑄造「無效指針」指向結構

#include <stdio.h> 
#include <stdlib.h> 
struct s1 { 
     int i; 
     void * p; 
    }; 
static struct s1 *dmk; 
int main(void) { 

    int tong(int a, int b); 
    int (*tinh)(int,int); 

    struct s2 { 
     int num; 
     int (*cal)(int a, int b); 
    }; 
    if(dmk->p == NULL) 
    { 
     printf("NULL ALERT\n"); 
    } 
    struct s2 *cl = dmk->p; 
    cl->cal = tong; 

    tinh = ((struct s2 *)(dmk->p))->cal; 
    printf("tinh 2, 4 ra %d\n",tinh(2,4)); 
    puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */ 
    return EXIT_SUCCESS; 
} 

int tong(int a, int b) 
{ 
    return a + b; 
} 

當我編譯它,它沒有表現出任何錯誤或警告。但是當我運行程序時,終端告訴我「核心轉儲」並沒有顯示任何結果接受「NULL ALERT」。誰能解釋我爲什麼失敗?非常感謝。

回答

3
if(dmk->p == NULL) 

dmk 未初始化 初始化爲NULL,指出「沒有地方」,所以去引用它調用未定義行爲失敗。之後會發生任何事情。

+0

在我引用的陳述中用' - >'調用UB是個問題。編碼器方面出現「*失敗*」。 @ T.J.Crowder – alk

+1

實際上'dmk' **被**初始化,因爲它是一個全局變量。問題:它是一個_null pointer_。 – Olaf

+0

@Olaf:正確,修正,謝謝。 – alk

2

底線是你在做錯的事情是在使用它們之前不把東西分配給你的各種指針。

您的dmk是全球性的,因此其初始值爲NULL。你永遠不會改變這個價值。

後來,你讀了dmk->p。您現在處於未定義行爲(UB)領域。該程序可能很容易出錯,因爲您正在從NULL指針讀取數據。

顯然它沒有,因爲你看到你的消息NULL ALERT,所以我們繼續。

然後你這樣做:

struct s2 *cl = dmk->p; 
cl->cal = tong; 

在第二行有,cl完全是不確定的。這可能是垃圾,可能是NULL,無論如何,因爲你進入了UB領土。然後你解引用它並寫入結果。你可能試圖在任何地方寫字。寫入隨機指針(或指針NULL)往往會導致核心轉儲和其他壞事情發生。

在使用它們之前,您需要爲指針實際賦值。

1

您不要在代碼中初始化dmk。那個dmk-> p是NULL是純粹的運氣。什麼事情都可能發生。

您需要使用例如malloc()爲您的結構分配內存,並正確初始化成員。

+3

實際上'dmk' **被**初始化,因爲它是一個全局變量。問題:它是一個_null pointer_。 – Olaf

2

dmk是一個全球性的(亦稱靜態的(這是相關static關鍵字!),可變的,因此它被初始化爲空指針。你不改變這個值,所以dkms->p取消引用一個空指針,它調用未定義行爲(UB)。

所以從這裏,這是炒作,因爲UB意味着任何事情都有可能發生

顯然printf通過,可能是因爲地址可以被讀取。以下寫入OTOH失敗,生成系統消息。