2013-05-02 51 views
0

我試圖創建一個函數,從任意類型放在一起的緩衝區。想想基本的RPC。所以緩衝區看起來像Memcpy字符串作爲void指針,不正確讀取

{ char opcode, uint32_t param1_size, param1, ... , uint32_t paramN_size, paramN } 

它似乎是工作,但從緩衝區提取數據時,它似乎並沒有正確解釋字符串。

int enqueue_into_buf(char *buf, size_t buf_pos, const uint32_t param_len, const void *param) { 

    /* If param_len is NULL, then change opcode */ 
    if(param_len == 0) { 
     memcpy(buf, param, 1); 
     if(buf_pos == 0) 
      buf_pos++; 
     return buf_pos; 
    } 

    memcpy(buf + buf_pos, &param_len, sizeof(param_len)); 
    buf_pos += sizeof(param_len); 

    memcpy(buf + buf_pos, param, param_len); 
    buf_pos += param_len; 

    return buf_pos; 
} 

int main(int argc, char *argv[]) 
{ 
    char opcode; 
    uint32_t param_len, num_params, buf_size, buf_pos = 0, received_num; 
    char *buf, *temp; 

    char *input_string = "file01"; /* example string to use as parameter */ 
    size_t input_size = 4, received_size; /* example variable to also use as a parameter */ 

    opcode = '1'; /* opcode equals function 1 */ 
    num_params = 2; /* number of parameters */ 

    /* setting the size of the buffer that will be sent over the network */ 
    buf_size = sizeof(opcode) + (num_params * sizeof(uint32_t)) + (strlen(input_string) * sizeof(char)) + sizeof(input_size); 
    buf = malloc(buf_size); 

    /* Notice the ampersand! */ 
    buf_pos = enqueue_into_buf(buf, buf_pos, 0, &opcode); 
    buf_pos = enqueue_into_buf(buf, buf_pos, strlen(input_string), &input_string); 
    buf_pos = enqueue_into_buf(buf, buf_pos, sizeof(input_size), &input_size); 

    /* At this point, since we inserted everything into the buffer, 
    the buffer size and current buffer position should be equal */ 
    if(buf_pos == buf_size) 
     printf("Calculated buffer size correctly and inserted everything correctly as well. Buffer size = %d\n", buf_size); 

    /** Extract from buffer **/ 
    buf_pos = 0; 

    printf("Opcode: %c\n", buf[buf_pos]); 
    buf_pos++; 

    memcpy(&received_num, buf + buf_pos, sizeof(uint32_t)); 
    printf("Size of parameter 1: %d\n", received_num); 
    buf_pos += sizeof(uint32_t); 

    temp = malloc(received_num + 1); 
    memcpy(temp, buf + buf_pos, received_num); 
    temp[received_num] = '\0'; 
    printf("Parameter 1: %s\n", temp); 
    buf_pos += received_num; 

    memcpy(&received_num, buf + buf_pos, sizeof(uint32_t)); 
    printf("Size of parameter 2: %d\n", received_num); 
    buf_pos += sizeof(uint32_t); 

    memcpy(&received_size, buf + buf_pos, sizeof(size_t)); 
    printf("Parameter 2: %d\n", received_size); 
    buf_pos += sizeof(size_t); 

    return 0; 
} 

編輯:代碼輸出:

Calculated buffer size correctly and inserted everything correctly as well. Buffer size = 23 
Opcode: 1 
Size of parameter 1: 6 
Parameter 1: @ @ 
Size of parameter 2: 8 
Parameter 2: 4 

我想我不能正確複製數據到緩衝器,因爲使用相同的參數(input_string = 「file01」,input_size = 4) ,此代碼的工作...

/* OPCODE */ 
    buf[buf_pos] = opcode; 
    buf_pos++; 

    /* PARAMETER 1 */ 
    param_len = (strlen(input_string) * sizeof(char)); /* size of parameter 1 */ 

    memcpy(buf + buf_pos, &param_len, sizeof(uint32_t)); 
    buf_pos += sizeof(uint32_t); 

    //memcpy(buf + buf_pos, &input_string, (strlen(input_string) * sizeof(char))); 
    strcat(buf + buf_pos, input_string); 
    buf_pos += strlen(input_string) * sizeof(char); 


    /* PARAMETER 2 */ 
    param_len = sizeof(input_size); 

    memcpy(buf + buf_pos, &param_len, sizeof(param_len)); /* same as saying sizeof(uint32_t) */ 
    buf_pos += sizeof(uint32_t); 

    memcpy(buf + buf_pos, &input_size, sizeof(input_size)); 
    buf_pos += sizeof(input_size); 

編輯:輸出代碼:

Calculated buffer size correctly and inserted everything correctly as well. Buffer size = 23 
Opcode: 1 
Size of parameter 1: 6 
Parameter 1: file01 
Size of parameter 2: 8 
Parameter 2: 4 

但顯然我不想使用strcat(),因爲我不知道它會是什麼樣的數據類型。我是否正確使用memcpy?

編輯:方案

回答

1

把輸出您自己突出的問題:

/* Notice the ampersand! */ 
buf_pos = enqueue_into_buf(buf, buf_pos, 0, &opcode); 
buf_pos = enqueue_into_buf(buf, buf_pos, strlen(input_string), &input_string); 

您已經聲明

char *input_string = "file01"; 

所以,當你通過&input_stringenqueue_into_buf,您要複製strlen(input_string)字節從指針input_string被存儲到緩衝區的位置開始。

通常,在64位系統上,這將是指針值的八個字節中的六個,在32位系統上指針的四個字節加兩個字節(調用未定義的行爲)。

但是要串"file01"複製到緩衝區,即什麼樣的指針指向,因此你不能傳遞指針的地址,但指針本身:

buf_pos = enqueue_into_buf(buf, buf_pos, strlen(input_string), input_string); 
                  // ^^ No address taken here! 
+0

有道理;我犯了這個錯誤。謝謝!! – 2013-05-02 17:55:38

1

有一對夫婦的問題在這裏。

第一:

buf_pos = enqueue_into_buf(buf, buf_pos, strlen(input_string), &input_string); 

你試圖通過第四個參數enque爲void *以及字符串已經是一個指針類型,所以傳遞字符串的地址是你想要的要做的只是:

buf_pos = enqueue_into_buf(buf, buf_pos, strlen(input_string), input_string); 

是正確的。

二:

你永遠不zero'ed你的BUF,所以你不知道什麼是坐在那裏:

buf = malloc(buf_size); 
memset(buf, 0, buf_size); // add this line here to clear the buffer before using it 

申報,分配,初始化......再使用。它會爲你節省很多頭痛。