2014-04-21 20 views
0

下面的C程序有不同的輸出,如果我寫我的主要功能裏面的東西,我真的不明白爲什麼..不確定性瑣碎的C程序

如果我們發表意見MYVARIABLE聲明,一切都很好,我們獲得期望的結果(應用3次SHA256到0x12345678)。但是,如果我在主函數中寫入任何內容,則輸出會發生變化並且不會達到期望的值。

如何聲明一個新的變量可能會影響到這一點?

的代碼(precompute.c):

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

#include <openssl/sha.h> 

unsigned char* sha256_3(int* input) { 
    char *s = (char*)input; 
    unsigned char *d = SHA256(s, strlen(s), 0); 
    d = SHA256(d, strlen(d), 0); 
    d = SHA256(d, strlen(d), 0); 

    return d; 
} 

void print_hash(unsigned char* d) { 
    int i; 
    for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 
     printf("%02x", d[i]); 
    putchar('\n'); 
} 

int main(int argc, const char * argv[]) { 
    int A = 0x12345678; 
    unsigned char *B = sha256_3(&A); 
    print_hash(B); 

    // int myVariable = 3; // Uncomment this line and recompile to see the difference 

    return EXIT_SUCCESS; 
} 

的生成文件:

CC=gcc 
CFLAGS=-c 
LDFLAGS=-lssl -lcrypto 
SOURCES=precompute.c 
OBJECTS=$(SOURCES:.c=.o) 
EXECUTABLE=hello 

all: $(SOURCES) $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
    $(CC) $(OBJECTS) -o [email protected] $(LDFLAGS) 

.c .o: 
    $(CC) $(CFLAGS) $< -o [email protected] 

clean: 
    rm -rf *o hello 

預期的輸出(MYVARIABLE的聲明註釋):

8f3d8f8c5eff23dc137762220cf24f140b7a1b804cc20442617 42fd73286c169

意外輸出(MYVARIABLE取消註釋的聲明):

663e9571f713f83b19c913938e2947c8fc0a7072d1fc442385857c456c43295b

非常感謝您!

+3

你從未分配過任何空間。你只是寫隨機存儲器(UB) –

+4

也幾乎沒有任何C這些行有任何意義。從相同的內存中讀取和寫入,重複寫入指針,就好像它們是基元一樣。這看起來不可兌換,只是重新開始。 –

+5

C字符串的長度由終止空字符決定,所以'strlen(s)'是UB,因爲's'只是指向某個內存塊 – Dabo

回答

0

通過分析這些片斷:

char *s = (char*)input; 
unsigned char *d = SHA256(s, strlen(s), 0); 

幾個錯誤就可以看出。 input最初是一個指向int的指針(由int A的行定義)。一個int通常有4個字節。當你將一個指針指向char *時,這很好,你的指針指向一個4字節的分配內存。但是,string.h中的所有函數(包括strlen())都依賴於字符串末尾存在NUL('\ 0')字符。基本上,strlen()計算有多少個字符,直到NUL。由於在int的4個字節之後沒有NUL字符,結果將基於內存中可找到的內容(內存中某處可能爲0,這是NUL字符的值,並且strlen停止) 。

現在,爲了解決這個問題,你有兩種可能的解決方案:或者從你需要的值開始創建一個字符串,或者在sha256_3函數中創建一個5字節的字符串,從int中複製4個字符串作爲參數並將NUL分配給最後一個。