memcpy()期间的段错误

时间:2011-11-11 09:11:10

标签: c

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

此程序引发了分段错误。我想读取一些字节的数据以及写入一些字节的数据。我已经编写了上面的代码,但它抛出一个错误作为seg错误。请帮我解决这个问题。

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

输出:

4 个答案:

答案 0 :(得分:3)

首先,您使用read()write()会影响系统提供的read(2)write(2)例程。这是一个巨大的错误。 (你可以替换系统提供的系统调用包装器,但你最好确保你做的就像系统C库作者首先编写它们一样好。你甚至不是< em>关闭系统提供的read(2)write(2)函数。)您的printf(3)调用会尝试在内部使用write(2)来编写输出,会找到你的实现。因为你的参数处理它的参数与write(2)实现完全不同,它可能会在memcpy()调用时死掉 - 你已经将write()的第一个参数解除引用,就好像它是一个指针一样,但是printf(3)会使用类似1的整数来调用它。解除引用1是一种确定的段错误方法。

其次,您不能在传递给函数的数组上使用sizeof作为参数。作为参数传递的数组衰减为指针 - 您的函数无法确定是否使用数组或字符指针调用它,并且sizeof将计算(在编译时!)指针的大小< / em>的。巨大的差异。要么在参数中传递数组大小,要么使用编译时#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),因此您可以直接使用对象。

我强烈建议在花费更多时间在这个程序之前阅读The C Programming Language by Kernighan and Ritchie - 尝试调试这个程序是一种非常缓慢的学习C的方法。

答案 1 :(得分:1)

AIUP_read中,您无法使用sizeof(data)!返回的大小将是指针的大小,而不是它指向的大小。您必须向函数AIUP_readAIUP_write提供数据长度。

答案 2 :(得分:1)

您的崩溃位于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);

答案 3 :(得分:1)

好的,这里有几个问题。首先,您使用sizeof似乎是错误的。在每种情况下,您似乎都在尝试读/写和audio_state结构,因此您应该使用sizeof(audio_state)来复制整个结构。 sizeof(data)可能会在32位机器上为4,在64位机器上为8,而sizeof(user_mem[pos])将为1。

其次,您的printf语句在一个案例中使用%c,在另一个案例中使用%s。我怀疑seg-fault的原因是这一行:

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

您告诉printf期待一个字符串(char*),但您传递的*dataunsigned charprintf会将此字符转换为char*并尝试访问该地址。因为它不是一个字符串,所以它会出错。