скопировать символьную строку в буфер без знака: ошибка сегментации

#c #segmentation-fault #buffer #memmove

#c #ошибка сегментации #буфер #memmove

Вопрос:

я пытаюсь скопировать два целых числа и символьную строку в буфер и распечатать элементы буфера. Я получаю ошибку seg для третьей инструкции printf:

     id = 102;
    len = 3;
    str = "working";
    memmove(buffer,amp;message_id,sizeof(id));
    memmove(buffer (sizeof(id)),amp;len,sizeof(len));
    memmove(buffer (2*sizeof(id)),amp;string, sizeof(str));

    printf("1 is: %dn", buffer[0]);
    printf("2 is: %dn", buffer[4]);
    printf("3 is %sn, buffer[8])); // here is where i get the seg fault should
    be a string
    /***/
    bufer is declared as unsinged char buffer[444];
  

Я не знаю, почему это приведет к ошибке seg?

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

1. что такое буфер с двумя «f», объявленный как — вы говорите, bufer — это символ без знака [444]

2. Как объявляются string и str ?

Ответ №1:

buffer[8] является a char , %s ожидает строки, что означает char * вместо этого передачу amp;buffer[8] . Ошибка сегментации возникает из-за того, что printf пытается обработать символ как указатель на символ, который является адресом (и если передается символ, он вряд ли будет допустимым)

РЕДАКТИРОВАТЬ: как прокомментировал Дэвид, если отправная точка для копирования строки связана со значениями перед ней, не используйте фиксированное значение, вместо amp;buffer[8] использования buffer (2*sizeof(id)) или buffer[2*sizeof(id)]

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

1. 1, хотя buffer 8 или еще лучше buffer 2*sizeof (int) было бы предпочтительнее

Ответ №2:

В вашем коде было несколько проблем, но наиболее важным моментом является то, что memmove() не копируется нулевой символьный байт строки.

Функция не проверяет наличие какого-либо завершающего нулевого символа в исходном коде — она всегда копирует ровно num байт.

Это дает вам два варианта:

  • Учитывайте это при копировании материала:

memmove(buffer sizeof(id) sizeof(len), str, strlen(str) 1);

  • Или после того, как память была скопирована, убедитесь, что строка заканчивается на '' (иначе. 0 ) в вашем буфере:

memmove(buffer sizeof(id) sizeof(len), str, strlen(str));

buffer[sizeof(id) sizeof(len) strlen(str) 1] = 0;

В любом случае, код теперь работает. Другая проблема заключалась в том, что вы пытались указать длину строки с помощью sizeof(str) . Это неправильно, и вы должны это делать strlen(str) . И последнее, чего в целях наглядности и безопасности не делайте 2*sizeof(id) . Если позже вы решите изменить тип переменной, вы облажались. Правильный путь был бы sizeof(id) sizeof(len) . Вот и все.

 int id = 102;
int len = 3;
char* str = "working";
char buffer[444];

memmove(buffer,amp;id,sizeof(id));
memmove(buffer (sizeof(id)), amp;len, sizeof(len));
memmove(buffer sizeof(id) sizeof(len), str, strlen(str));
buffer[sizeof(id)  sizeof(len)   strlen(str)   1] = 0;

printf("1 is: %dn", buffer[0]);
printf("2 is: %dn", buffer[4]);
printf("3 is: %sn", amp;buffer[8]);
  

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

1. отличное объяснение. Большое спасибо. я забыл использовать strlen и учитывать нулевой символ

Ответ №3:

Основная проблема заключается в том, что вы пытаетесь напечатать строку, передавая только символ. Это потому, что buffer[8] ссылается на char с индексом 8, а не на строку, начинающуюся с этой позиции. Итак, вам нужно взять адрес buffer[8] , чтобы превратить его в строку или char* .

Причина, по которой происходит сегментация, заключается в том, что printf пытается напечатать строку, начинающуюся с адреса, указанного первым символом (т.Е. само содержимое строки), которое не является допустимым указателем.

Также имеется ряд опечаток и ошибок. Рабочая версия приведена ниже:

 #include <stdio.h>
#include <memory.h>

int main()
{
    unsigned char buffer[444];
    int id = 102;
    int len = 3;
    char* str = "working";

    memmove(buffer,amp;id,sizeof(id));
    memmove(buffer (sizeof(id)),amp;len,sizeof(len));
    memmove(buffer (2*sizeof(id)), str, sizeof(str));

    printf("1 is: %dn", buffer[0]);
    printf("2 is: %dn", buffer[4]);
    printf("3 is %sn", amp;buffer[8]);

    return 0;
}
  

Если вы скомпилировали это приложение со всеми включенными предупреждениями (т.Е. -Wall ), ваш компилятор (по крайней мере, GCC) должен предупредить вас о вашей ошибке следующим образом:

 problem.c:18: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int 

Предупреждения не следует игнорировать!