简体   繁体   中英

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);
}

This program is throwing a segmentation fault. I wanted to read some bytes of data as well as to write some bytes of data. I have written the above code but it's throwing an error as seg fault. Please help me to resolve this issue.

EDITED

#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));
}

output:

First, your use of read() and write() shadows the system-supplied read(2) and write(2) routines. This is a giant mistake. (You can replace the system-supplied system call wrappers but you had better make sure you do as good a job programming them as the system C library authors did in the first place. Yours aren't even close to what the system-supplied read(2) and write(2) functions do.) Your printf(3) call will try to use write(2) internally to write your output and will find your implementation instead. Because yours handles its parameters very differently than the write(2) implementation, it'll probably die on that memcpy() call -- you've dereferenced the first argument to write() as if it were a pointer, but printf(3) will call it with an integer like 1 . Dereferencing 1 is a sure-fire way to segfault.

Second, you cannot use sizeof on an array passed into a function as a parameter. Arrays passed as parameters decay to pointers -- your function cannot determine if it was called with an array or a character pointer, and sizeof is going to calculate (at compile time!) the size of a pointer . Huge difference. Either pass array sizes in the parameters or use compile-time #defines to make them the same across the whole project.

Third:

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

This has the effect of passing a single character to printf(3) but your format string suggested you were going to pass a "string". C strings are NUL -terminated char arrays -- who knows when the next '\\0' byte in the input you've given it is going to come.

Fourth:

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

You're making dangerous (and needless) casts away from your structure type to a completely unrelated type. Your new write() replacement should look something more like void write_aud(audio_state *a) , so you can work with your objects directly.

I strongly recommend reading The C Programming Language by Kernighan and Ritchie before spending much more time on this program -- trying to debug this one into existence is going be a painfully slow way to learn C.

In AIUP_read you can not use sizeof(data) ! The size returned will be that of the pointer , not what it points to. You must supply the length of data to the functions AIUP_read and AIUP_write .

Your crash is in AIUP_write :

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

you are attempting to read a string, thus crashing (change to '%d' to print the value of vol_level ).

There are other logic issues, related to the use of sizeof and the use of pos , which is always 0.

A debugger shows these problems quite easily:

(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);

Ok, there's a couple of problems here. First, your use of sizeof seems to be wrong. In each case it looks like you're trying to read/write and audio_state structure, so you should be using sizeof(audio_state) to copy the entire structure. sizeof(data) will probably give you 4 on a 32bit machine and 8 on a 64bit machine, while sizeof(user_mem[pos]) is going to be 1.

Secondly, your printf statements are using %c in one case and %s in another. I suspect the reason for the seg-fault is the line:

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

You're telling printf to expect a string (a char* ) but you're passing in *data which is an unsigned char . printf will cast this char to a char* and try to access the address. Since it's not a string it's going to fault.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM