Общая память иногда не обнуляется - PullRequest
4 голосов
/ 21 февраля 2012
// reading                        
if((shmid = shmget(key, 0, 0)) < 0) {                  
    perror("shmget");                
    exit(50); 
}                                                         

// attach                                                 
if((data = shmat(shmid, (void *)0, 0)) == (char *) -1) {        
    perror("shmat");                                      
    exit(100);                                            
}

// get memory size
struct shmid_ds shm_info;
size_t shm_size;
int shm_rc;
if((shm_rc = shmctl(shmid, IPC_STAT, &shm_info)) < 0)
    exit(101);
shm_size = shm_info.shm_segsz;

Иногда данные не заканчиваются нулем, и вызов strlen (data) вызывает ошибки по умолчанию ...

Итак, я пытался убедиться, что он завершен нулем, набрав

data[shm_size] = '\0';

Но теперь иногда происходит сбой в этой строке кода.

Что я делаю не так?

РЕДАКТИРОВАТЬ: Спасибо за вашу поддержку! Я думаю, что после вашего объяснения о strlen () + 1 == shm_size я изменил остальную часть моего кода, который не был размещен здесь, и кажется, что все в порядке. Я жду новых segfaults и, надеюсь, я не получу;)

Ответы [ 5 ]

3 голосов
/ 21 февраля 2012

первый: память не должна иметь нулевое завершение. это не определено в начале. Вы можете рассмотреть возможность использования

memset(data,0,shm_size);

и второй:

data[shm_size] = '\0';

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

data[shm_size-1] = '\0';
3 голосов
/ 21 февраля 2012

Массивы 0 -оригина, вы хотите:

data[shm_size - 1] = '\0';
2 голосов
/ 21 февраля 2012

Делая

`data[shm_size] = '\0';` 

, вы фактически получаете доступ к области памяти за пределами границ разделяемой памяти ... синтаксис data[index_value] для указателя, указывающего на необработанныйблок памяти аналогичен поговорке

*(data + index_value*sizeof(unsigned char))  

. Таким образом, data[0] будет разыменовывать и возвращать значение по первому адресу памяти в сегменте общей памяти, а data[shm_size] будет делать то же самое по адресу и адресу послеконец сегмента разделяемой памяти.

2 голосов
/ 21 февраля 2012

Назначение нулевого символа завершения:

data[shm_size] = '\0';

записывает после конца выделенной памяти, что составляет неопределенное поведение .Если в буфере есть символьные данные длиной shm_size, то необходимо будет скопировать его в другой буфер, чтобы завершить его с нулевым значением.

1 голос
/ 21 февраля 2012

data[shm_size] - один за концом. Вместо этого вы должны сделать data[shm_size-1], и только если shm_size != 0.

Но, тем не менее, вызов strlen() имеет смысл только в том случае, если вы действительно поместили в него строку. В противном случае он может вернуть любое значение < shm_size, если есть символ \0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...