简体   繁体   English

C-将整个结构写入共享内存的困难

[英]C - Difficulties writing whole struct to Shared Memory

I'm having problems writing a structure to shared memory because when I do, the code only writes the first part of the structure. 我在将结构写入共享内存时遇到问题,因为这样做时,代码仅写入结构的第一部分。

Here's my data structure: 这是我的数据结构:

struct shmData{
    char number[4];
    char description[1020];
};

Here's my code: 这是我的代码:

//Structure Pointer - placed on SHM
struct shmstruct *ptr;
char description_to_write[1024] = {0};
struct shmData *data_ptr;
data_ptr = (struct shmData*) description_to_write;

//Shared Memory init
create_shm(&ptr);
printf("Started\n");

//Define Offsets
//init_shm(ptr);

//#########################

//Check if number exist
    if (!(strcmp("NO SUCH CODE\0", get_description(ptr, 6)))) {
        //-> If not, get next offset (nput) where to write new data
//      sem_wait(&ptr->mutex);
//      long offset = ptr->msgoff[ptr->nput];
//      printf("OFFSET: %li\n", offset);
//      if (++(ptr->nput) > NMESG)
//          ptr->nput = 0; /* circular buffer */
//      sem_post(&ptr->mutex);
//      printf("Buffer: %s", argv[2]);

    snprintf(data_ptr->number, 4, "%s", "6");
    snprintf(data_ptr->description, 1020, "%s\n", argv[2]);

    printf("DATA: %s\n", data_ptr->number);
    printf("DATA: %s\n", data_ptr->description);

    printf("description_to_write: %i\n", description_to_write);

    //strcpy(&ptr->msgdata[offset], );
    //sem_post(&ptr->nstored);
    //printf("Wrote...\n\n");
} else {
    //-> Else get offset of this number and put data to it
}

How should I write this? 我该怎么写? In the code above, I tried simply to display the description array but I only get the number back. 在上面的代码中,我只是尝试显示描述数组,但我只得到了数字。

I need it to be written to shared memory as follows: 我需要将其写入共享内存,如下所示:

Number(space)(space)(space)Description

Shared Memory Dump looks like: 共享内存转储看起来像:

00003b0: 3120 2020 496e 7075 7420 4572 726f 720a  1   Input Error.
00003c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
00007b0: 3220 2020 4f75 7470 7574 2045 7272 6f72  2   Output Error
00007c0: 0a00 0000 0000 0000 0000 0000 0000 0000  ................
00007d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

From debugger: 从调试器:

description_to_write[0] char    54 '6'  
description_to_write[1] char    0 '\000'    
description_to_write[2] char    0 '\000'    
description_to_write[3] char    0 '\000'
description_to_write[4] char    83 'S'  
description_to_write[5] char    111 'o' 
description_to_write[6] char    109 'm' 
description_to_write[7] char    101 'e' 
description_to_write[8] char    84 'T'  
description_to_write[9] char    101 'e' 
description_to_write[10]char    120 'x' 
description_to_write[11]char    116 't' 
description_to_write[12]char    10 '\n' 

Ugly solution: 丑陋的解决方案:

int i = 0;
        while(i < 4){
            if(data_ptr->number[i] == '\000'){
                data_ptr->number[i] = 32;
            }
            i++;
        }

The 4 passsed to snprintf specifies the MAXIMUM number of chars to write. 传递给snprintf的4指定要写入的最大字符数。 Not the amount to write. 没有写的数量。 snprtinf retursn the number of chars it did write. snprtinf取消它确实写入的字符数。 So you are only printing 1 char, which leaves 3 nulls after it. 因此,您仅打印1个字符,其后留3个空值。

Just do: 做就是了:

snprintf(data->number,4,"%s    ","6");

That way it will try and print the string followed by 4 spaces, and print a max of 4 charcacters. 这样,它将尝试打印字符串,后跟4个空格,并最多打印4个字符。

Your ugly solution to use snprintf() and then rewrite '\\0' characters as spaces has some flaws: 您使用snprintf()然后将'\\ 0'字符重写为空格的丑陋解决方案存在一些缺陷:

  • snprintf() will never write a digit into data_ptr->number[3] . snprintf()永远不会将数字写入data_ptr->number[3] For strings longer than 3 characters it will truncate and write a '\\0' instead of copying the 4th character in the source string. 对于长度超过3个字符的字符串,它将截断并写入'\\ 0',而不是在源字符串中复制第4个字符。

  • unless you're sure that the structure will be zero initialized before calling snprintf() then characters after the '\\0' that snprintf() is required to write will not be set to anything by snprintf() . 除非你确信结构将零之前调用初始化snprintf()那么“\\ 0”,经过字符snprintf()被要求写不会被任意设置snprintf() That might not be a problem in your code as posted, but it's fragile in the face of changes to how the structure data_ptr points to is allocated and initialized. 在您发布的代码中,这可能不是问题,但是面对分配和初始化data_ptr指向结构的更改时,它是脆弱的。

Since the field is so small, you might consider something like: 由于该字段很小,因此您可以考虑以下内容:

memset( data_ptr->number, ' ', sizeof(data_ptr->number));
memcpy( data_ptr->number, "6", strlen("6"));

That still has a drawback that you need to add a bit more logic if the source string can possibly be longer than the field size. 这仍然有一个缺点,如果源字符串可能比字段大小长,则需要添加更多的逻辑。 Also, if it's something that you'll be doing in more than one or two spots it can easily become a source of copy/paste bugs. 另外,如果您要在一个或两个以上的地方进行操作,则很容易成为复制/粘贴错误的来源。

Here's a lightly tested function that you can use instead (though I'll admit that I hate the name): 这是一个经过严格测试的函数,您可以代替使用(尽管我承认我讨厌这个名称):

size_t str2mem_padded( char* dest, size_t dest_size, char const* src, char fill)
{
    size_t result = 0;

    while (dest_size && *src) {
        *dest++ = *src++;
        ++result;
        --dest_size;
    }
    while (dest_size) {
        *dest++ = fill;
        --dest_size;
    }

    return result; // returns number of chars copied from src so you 
                   //   can determine if there was truncation
}

In your code, you might use the following instead of the call to snprintf(data_ptr->number, 4, "%s", "6") : 在您的代码中,您可以使用以下代码代替对snprintf(data_ptr->number, 4, "%s", "6")的调用:

str2mem_padded( data_ptr->number, sizeof(data_ptr->number), "6", ' ');

Wow - that was a lot more effort than I thought it would be. 哇-那比我想象的要多得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM