ошибка seg во время memcpy()

#c

#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,amp;user_mem[pos],sizeof(data));
    printf("The Read data is:%c",*data);
}

void aud_write(unsigned char * data)
{
    unsigned short pos =0;
    memcpy(amp;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*)amp;aud_stat);
    aud_read((unsigned char*)amp;aud_stat);
}
  

Эта программа выдает ошибку сегментации. Я хотел прочитать несколько байтов данных, а также записать несколько байтов данных. Я написал приведенный выше код, но он выдает ошибку как ошибку seg. Пожалуйста, помогите мне решить эту проблему.

ОТРЕДАКТИРОВАНО

 #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,amp;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(amp;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*)amp;aud_stat,sizeof(audio_state));
    read((unsigned char*)amp;aud_stat,sizeof(audio_state));
}
  

вывод:

Комментарии:

1. Вы запускали это через отладчик? Вы проверили, что указатели, данные memcpy , были действительными?

2. Я использую codepad. У меня не установлено программное обеспечение на C.

3. @Angus: Я предлагаю вам получить один.

4. Почему этот вопрос был отклонен? Это кажется справедливым вопросом, и это подчеркивает важность отладчика при работе с указателями.

Ответ №1:

Во-первых, ваше использование 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 — кто знает, когда придет следующий '' байт во введенных вами входных данных.

Четвертый:

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

Вы выполняете опасные (и ненужные) приведения от вашего структурного типа к совершенно не связанному типу. Ваша новая write() замена должна выглядеть как-то более похоже void write_aud(audio_state *a) , чтобы вы могли работать с вашими объектами напрямую.

Я настоятельно рекомендую прочитать The C Programming Language Кернигана и Ричи, прежде чем тратить гораздо больше времени на эту программу — попытка отладить ее до появления будет мучительно медленным способом изучения C.

Ответ №2:

В AIUP_read вы не можете использовать sizeof(data) ! Возвращаемый размер будет соответствовать размеру указателя, а не тому, на что он указывает. Вы должны указать длину данных для функций AIUP_read и AIUP_write .

Комментарии:

1. Я выполняю strlen (данные) и strlen(user_mem [pos]). Правильно ли это. Пожалуйста, помогите

Ответ №3:

Ваш сбой в 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);
  

Ответ №4:

Хорошо, здесь есть пара проблем. Во-первых, ваше использование sizeof кажется неправильным. В каждом случае похоже, что вы пытаетесь читать / записывать и audio_state структурировать, поэтому вы должны использовать sizeof(audio_state) для копирования всей структуры. sizeof(data) вероятно, это даст вам 4 на 32-разрядной машине и 8 на 64-разрядной машине, в то время как sizeof(user_mem[pos]) это будет 1.

Во-вторых, ваши printf инструкции используются %c в одном случае и %s в другом. Я подозреваю, что причиной ошибки seg является строка:

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

Вы говорите, printf что ожидаете строку (a char* ), но вы передаете, *data что является unsigned char . printf преобразует этот символ в a char* и попытается получить доступ к адресу. Поскольку это не строка, это приведет к сбою.

Комментарии:

1. Шон: ты прав!. Я не получил ошибок. Но не удалось распечатать выходные данные. Пожалуйста, посмотрите правку

2. Пожалуйста, помогите мне определить, где ошибка!.