简体   繁体   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);
}

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. 首先,对read()write()掩盖系统提供的read(2)write(2)例程。 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. (您可以替换系统提供的系统调用的包装,但你最好确保你做的一样好工作他们作为编程系统C库笔者在第一时间做了。您甚至没有接近到什么系统提供的read(2)write(2)函数都可以。)您的printf(3)调用将尝试在内部使用write(2)来编写输出,并找到您的实现。 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 . 因为您处理参数的方式与write(2)实现的方式非常不同,所以它可能会死于memcpy()调用-您已经取消引用write()的第一个参数,就好像它是一个指针一样,但是printf(3)会使用1这样的整数来调用它。 Dereferencing 1 is a sure-fire way to segfault. 取消引用1是确定段的可靠方式。

Second, you cannot use sizeof on an array passed into a function as a parameter. 其次,您不能在传递给函数的数组中使用sizeof作为参数。 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 . 作为参数传递的数组会衰减到指针-您的函数无法确定是使用数组还是字符指针调用了它,并且sizeof将要计算(在编译时!) 指针的大小。 Huge difference. 差异很大。 Either pass array sizes in the parameters or use compile-time #defines to make them the same across the whole project. 在参数中传递数组大小,或者使用编译时#defines在整个项目中使它们相同。

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". 这具有将单个字符传递给printf(3)的效果,但是格式字符串建议您将要传递“字符串”。 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. C字符串是NUL终止的char数组-谁知道您输入中的下一个'\\0'字节何时到达。

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. 新的write()替换看起来应该更像是void write_aud(audio_state *a) ,因此您可以直接使用对象。

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. 我强烈建议您先花Kernighan和Ritchie的C编程语言,然后再花更多的时间在该程序上-尝试调试该程序以使其成为现实,这将是一种学习C的痛苦缓慢的方法。

In AIUP_read you can not use sizeof(data) ! AIUP_read您不能使用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 . 您必须将数据的长度提供给函数AIUP_readAIUP_write

Your crash is in AIUP_write : 您的崩溃是在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 ). 您正在尝试读取字符串,从而崩溃(更改为'%d'以显示vol_level的值)。

There are other logic issues, related to the use of sizeof and the use of pos , which is always 0. 还有其他逻辑问题,与使用sizeof和pos (始终为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. 首先,您对sizeof的使用似乎是错误的。 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. 在每种情况下,您似乎都在尝试读取/写入和audio_state结构,因此您应该使用sizeof(audio_state)复制整个结构。 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. 在32位计算机上, sizeof(data)可能会给您4,在64位计算机上, sizeof(data)会给您8,而sizeof(user_mem[pos])将会是1。

Secondly, your printf statements are using %c in one case and %s in another. 其次,您的printf语句在一种情况下使用%c ,在另一种情况下使用%s 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期待一个字符串(一个char* ),但是您要传入*data ,它是一个unsigned char printf will cast this char to a char* and try to access the address. printf将此字符转换为char*并尝试访问该地址。 Since it's not a string it's going to fault. 由于它不是字符串,因此会出错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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