簡體   English   中英

memcpy()期間出現段錯誤

[英]seg fault during memcpy()

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

#define USER_MEM (10*1024)

typedef struct {
    unsigned short int vol_level;
    int mute_stat;
}audio_state;

static audio_state aud_stat;

static unsigned char user_mem[USER_MEM];

void aud_read(unsigned char * data)
{
    unsigned short pos =0;
    memcpy(data,&user_mem[pos],sizeof(data));
    printf("The Read data is:%c",*data);
}

void aud_write(unsigned char * data)
{
    unsigned short pos =0;
    memcpy(&user_mem[pos],data,sizeof(user_mem[pos]));
    printf("The written data is:%s",*data);
}

int main()
{  
    aud_stat.vol_level=10;
    aud_stat.mute_stat=20;

    aud_write((unsigned char*)&aud_stat);
    aud_read((unsigned char*)&aud_stat);
}

該程序引發分段錯誤。 我想讀取一些字節的數據以及寫入一些字節的數據。 我已經寫了上面的代碼,但是它拋出了一個錯誤,作為段錯誤。 請幫助我解決此問題。

已編輯

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

#define USER_MEM (10*1024)

typedef struct {
    unsigned short int vol_level;
    int mute_stat;
}audio_state;

static audio_state aud_stat;

static unsigned char user_mem[USER_MEM];

void read(unsigned char * data,unsigned short num)
{
    printf("Into Read!\n");
    unsigned short pos =0;
    memcpy(data,&user_mem[pos],num);
    printf("The Read data is:%c",*data);
}

void write(unsigned char * data,unsigned short num)
{
    printf("Into Write!\n");
    unsigned short pos =0;
    memcpy(&user_mem[pos],data,num);
    printf("The written data is:%c",*data);
}

int main()
{
    aud_stat.vol_level=10;
    aud_stat.mute_stat=20;
    write((unsigned char*)&aud_stat,sizeof(audio_state));
    read((unsigned char*)&aud_stat,sizeof(audio_state));
}

輸出:

首先,對read()write()掩蓋系統提供的read(2)write(2)例程。 這是一個巨大的錯誤。 (您可以替換系統提供的系統調用的包裝,但你最好確保你做的一樣好工作他們作為編程系統C庫筆者在第一時間做了。您甚至沒有接近到什么系統提供的read(2)write(2)函數都可以。)您的printf(3)調用將嘗試在內部使用write(2)來編寫輸出,並找到您的實現。 因為您處理參數的方式與write(2)實現的方式非常不同,所以它可能會死於memcpy()調用-您已經取消引用write()的第一個參數,就好像它是一個指針一樣,但是printf(3)會使用1這樣的整數來調用它。 取消引用1是確定段的可靠方式。

其次,您不能在傳遞給函數的數組中使用sizeof作為參數。 作為參數傳遞的數組會衰減到指針-您的函數無法確定是使用數組還是字符指針調用了它,並且sizeof將要計算(在編譯時!) 指針的大小。 差異很大。 在參數中傳遞數組大小,或者使用編譯時#defines在整個項目中使它們相同。

第三:

 void write(unsigned char * data) /* .... */ printf("The written data is:%s",*data); 

這具有將單個字符傳遞給printf(3)的效果,但是格式字符串建議您將要傳遞“字符串”。 C字符串是NUL終止的char數組-誰知道您輸入中的下一個'\\0'字節何時到達。

第四:

 void write(unsigned char * data) /* ... */ aud_stat.mute_stat=20; write((unsigned char*)&aud_stat); 

您正在將危險的(且不必要的)強制轉換從結構類型轉換為完全不相關的類型。 新的write()替換看起來應該更像是void write_aud(audio_state *a) ,因此您可以直接使用對象。

我強烈建議您先花Kernighan和Ritchie的C編程語言,然后再花更多的時間在該程序上-嘗試調試該程序以使其成為現實,這將是一種學習C的痛苦緩慢的方法。

AIUP_read您不能使用sizeof(data) 返回的大小將是指針的大小,而不是其指向的大小。 您必須將數據的長度提供給函數AIUP_readAIUP_write

您的崩潰是在AIUP_write

printf("The written data is:%s",*data);

您正在嘗試讀取字符串,從而崩潰(更改為'%d'以顯示vol_level的值)。

還有其他邏輯問題,與使用sizeof和pos (始終為0)有關。

調試器很容易顯示這些問題:

(gdb) r
Starting program: /private/tmp/a.out 
Reading symbols for shared libraries +........................ done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x00007fff8e22e4f0 in strlen ()
(gdb) bt
#0  0x00007fff8e22e4f0 in strlen ()
#1  0x00007fff8e1cf8c3 in __vfprintf ()
#2  0x00007fff8e1ce18e in vfprintf_l ()
#3  0x00007fff8e1d72d0 in printf ()
#4  0x0000000100000e12 in write (data=0x100003880 "\n") at test2.c:26
#5  0x0000000100000e4e in main () at test2.c:33
(gdb) list 26,26
26  printf("The written data is:%s",*data);

好的,這里有兩個問題。 首先,您對sizeof的使用似乎是錯誤的。 在每種情況下,您似乎都在嘗試讀取/寫入和audio_state結構,因此您應該使用sizeof(audio_state)復制整個結構。 在32位計算機上, sizeof(data)可能會給您4,在64位計算機上, sizeof(data)會給您8,而sizeof(user_mem[pos])將會是1。

其次,您的printf語句在一種情況下使用%c ,在另一種情況下使用%s 我懷疑出現段錯誤的原因是:

printf("The written data is:%s",*data);

您要讓printf期待一個字符串(一個char* ),但是您要傳入*data ,它是一個unsigned char printf將此字符轉換為char*並嘗試訪問該地址。 由於它不是字符串,因此會出錯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM