edo888
edo888

Reputation: 418

Shared Memory sometimes not null terminatied

// 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;

Sometimes data is not null terminated and calling strlen(data) causes segfaults...

So I was trying to make sure that it is null terminated by making

data[shm_size] = '\0';

But now sometimes it fails on that line of code.

What I'm doing wrong?

EDIT: Thanks for your support! I think after your explanation about the strlen() + 1 == shm_size I have changed the rest of my code not posted here and seems to be fine. I'm waiting for new segfaults and hopefully I will not get any ;)

Upvotes: 4

Views: 353

Answers (5)

Jason
Jason

Reputation: 32530

By doing

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

you're actually accessing a memory region outside the bounds of the shared memory ... the data[index_value] syntax on a pointer pointing to a raw memory block is the same as saying

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

Thus data[0] will dereference and return the value at the first memory address in the shared memory segment, and data[shm_size] will do the same at and address past the end of the shared-memory segment.

Upvotes: 2

glglgl
glglgl

Reputation: 91099

data[shm_size] is one beyond the end. You should, instead, do data[shm_size-1], and only if shm_size != 0.

But nevertheless, calling strlen() makes only sense if you really have put a string inside it. Otherwise, it might return any value < shm_size if there happens to be a \0 character.

Upvotes: 1

Hayt
Hayt

Reputation: 5370

first: the memory has not to be null terminated. it is undefined at the beginning. you might want to consider using

memset(data,0,shm_size);

and second:

data[shm_size] = '\0';

is wrong by one index. arrays begin at zero so you should use

data[shm_size-1] = '\0';

Upvotes: 3

Mark Wilkins
Mark Wilkins

Reputation: 41242

The assignment of the null termination character:

data[shm_size] = '\0';

is writing past the end of the allocated memory, which is undefined behavior. If it the buffer has character data of length shm_size, then it will be necessary to copy it to another buffer in order to null terminate it.

Upvotes: 2

ouah
ouah

Reputation: 145899

Arrays are 0-origin, you want:

data[shm_size - 1] = '\0';

Upvotes: 3

Related Questions