2014-02-17 61 views
3

我在使用memcpy從緩衝區中提取數據時遇到了一些困難。C - 從緩衝區中提取數據的問題。可能與內存有關

首先,我memcpy的一些變量到緩衝區:

int l1_connect(const char* hostname, int port) { 
    // Variables to be stored in the buffer 
    char *msg = "Hi, I'm a message"; // strlen(msg) == 17 
    uint16_t sender_id = htons(1); // sizeof(sender_id) == 2 
    uint16_t packet_size = htons(sizeof(packet_size)+sizeof(sender_id)+strlen(msg)); // sizeof(packet_size) == 2 

    // Checking values 
    printf("l1_connect():\nsender_id: %d, packet_size: %d\n\n", ntohs(sender_id), ntohs(packet_size)); 
    // sender_id == 1, packet_size == 21 

    // The buffer 
    char buf[100]; 

    // Copying everything 
    memcpy(&buf, &sender_id, sizeof(sender_id)); 
    memcpy(&buf+sizeof(sender_id), &packet_size, sizeof(packet_size)); 
    memcpy(&buf+sizeof(sender_id)+sizeof(packet_size), &msg, strlen(msg)); 

    // Passing buf to another function 
    int bytes_sent = l1_send(1, buf, sizeof(buf)); 
} 

我然後嘗試提取數據(檢查,發送通過UDP套接字之前):

int l1_send(int device, const char* buf, int length) { 
    // Variables in which to store extracted data 
    uint16_t id = 0; 
    uint16_t size = 0; 
    char msg[50]; 

    memcpy(&id, &buf, sizeof(id)); 
    memcpy(&size, &buf+sizeof(id), sizeof(size)); 

    int remaining = ntohs(size) - (sizeof(id) + sizeof(size)); 
    printf("l1_send():\nremaining: %d\n", remaining); // -37041 

    // memcpy-ing with correct(?) offset 
    memcpy(&msg, &buf+sizeof(id)+sizeof(size), 50); 

    msg[49] = '\0'; 

    printf("id: %d\n", ntohs(id));  // 8372 
    printf("size: %d\n", ntohs(size)); // 37045 
    printf("msg: %s\n", msg);   // ��$_� 

    return 0; // For now 
} 

正如你所看到的,價值不是我所期望的。誰能告訴我我做錯了什麼?

回答

6

你的指針數學是不正確。您正在使用&buf,您應該只使用buf。如果這並不能說明什麼是錯的,沒有別的我可以說的意願:

#include <stdio.h> 

int main(int argc, char **argv) 
{ 
    char buff[100]; 
    printf("buff : %p\nbuff+10 : %p\n&buff+10 : %p\n", buff, buff+10, &buff+10); 
    return 0; 

} 

輸出(因平臺而異,很明顯)

buff : 0xbf87a8bc 
buff+10 : 0xbf87a8c6 
&buff+10 : 0xbf87aca4 

See it live。你正在做的數學是按類型遞增的,對於&buf是指向數組100 char s的指針;不是簡單的char地址。因此,&buff + 10(在我的示例中)說:「給我第100個字符的數組,從我現在的位置開始。」隨後的寫入會調用未定義的行爲。

Valgrind是你的朋友在這裏,順便說一句。它會在心跳中引起這一點。


更新

可能也填補了整個開局,而我在這裏。這也是錯誤的l1_send

memcpy(&id, &buf, sizeof(id)); 
// this------^ 

和你使用它在該函數隨後的其他領域。您正在獲取參數指針的地址,而不是其中的值。我相信你也需要buf

+0

你很對!我真的不明白何時使用&符號,哈哈。謝謝一堆! – Plasma

+1

它有助於記住'&'總是作爲一個地址輸入到它所在的變量中進行計算。數組並不是一個例外。指針都不是(就像我添加的更新中的情況那樣)。數組的「值」(在裸表達式中使用時)是其0元素的地址,其類型是指向元素的指針;不是指向數組元素的指針。我知道這似乎有點令人生畏,但一段時間後,它會來。 – WhozCraig

3

試試這個:

memcpy(buf, &sender_id, sizeof(sender_id)); 
memcpy(buf + sizeof(sender_id), &packet_size, sizeof(packet_size)); 
memcpy(buf + sizeof(sender_id) + sizeof(packet_size), msg, strlen(msg)); 

爲了幫助你瞭解什麼是你的代碼錯誤,你可以閱讀this

相關:Pointer math vs. Array index